Shiny

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.

There is a minimal, mostly statically linked binary that runs on many Linux distros. To keep it small and fast, it lacks features like a full readline console and MySQL client support. For everything else, build from the source. See the different build options in the Makefile.

an example up front

This is a little script I use to dump radio streams from an RSS feed supplied by my ISP.

#!/home/sean/bin/shiny

unless find: args[2]?
	oops "missing find parameter" bye
end

# rss is pulled in by cron
rss: io.slurp '/home/sean/.radio.rss'

# grab the first channel only
items: rss.alter ~^.*<channel>(.*)<\/channel>.*$~gsm
	action a end

# extract an xml tag
search: action txt, tag: in
    out if txt.match ~<%(tag)s>\s*(.*?)\s*</%(tag)s>~sm a else 'unknown' end
end

# cycle through radio stations searching name and description fields
for items.find ~<item>(.*?)</item>~sm
    name: search { a 'title' }
    link: search { a 'link'  }
    desc: search { a 'description' }
    if name.match ~%(find)s~i or desc.match ~%(find)s~i
        say "%s\n\t%s\n\t%s" name desc link
    end
end

Data Types

Variables

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 casting 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

Numbers are all floating point (real). There is no internal distinction between integers and decimals. The common infix arithmetic can be used with C-like precedence:

> 1+2/3
1.67

A math library is available:

> x: -42
> math.abs x
42
> 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 methods as the x numeric variable's methods.

Numbers are passed by value.

Math Library Functions

More to come.

Strings

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.

> string.length x
11
> x.length
11

Strings are passed by value.

String Library Methods

More to come.

Regex

Regular Expressions are used with various string library methods. They are specified using an ~pattern~flags notation, with Perl compatible syntax and modifier flags.

> x: 'hello world'
> x.alter ~[aeiou]+~ '_'
h_llo world
> x.split ~\s+~
object 152684360
 0: hello
 1: world
> if x.match ~hello~ 'yes!' else '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 ~(\w+)\s+(\w+)~
> a
hello
> b
world

Regex are passed by value.

Actions

Actions are an executable data type filling the role of functions/procedures/routines, etc. They can be assigned to a variable name or passed around as nameless blocks of code. The global variable scope is just another object, so global words can be considered functions/routines/procedures too - they are all the same thing.

say_hi: action
   print 'hi!'
end

Actions can import arguments with the in key word. Arguments are supplied to actions by placing them inline after the action call separated only by white space, without parentheses or commas.

say_hi_to: action
   print "hi %s!" in
end

say_hi_to 'tom'

Actions can return zero or one value with the out key word:

max_value: action
   a: in b: in
   out if a > b a else b end
end

print max_value 1 2

An action has a local variable scope. Variables in the local scope, the parent object scope, and the global scope are directly visible to an action by name. However, to write to a variable outside the local scope, a specific scope prefix must be used.

Actions are passed by reference.

Objects

Objects are closures. They use a prototype framework to create new objects either directly or by cloning. Any actions 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 object prototype:

x: new object
   greet: 'hi'
   say_hi: action
      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: new x
   greet: 'hello there'
end

y.say_hi

Objects can also be created and used as associative arrays, using JSON syntax:

array: { a: 1, b: 2, c: 'three' }

Object actions 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.

Super Prototype

More to come.

Control Structures

All control structures and code blocks end with the end key word.

if else

if condition [or|and condition [...]]
   block
else
   block
end

while

while condition [or|and condition [...]]
   block
end

for

for iterable key var
   block
end

All control structures also return the last value generated in their code block. For example, this allows Shiny's normal if else end to act like the C ternary operator:

variable: if condition <true_value> else <false_value> end

(The above should look familiar to Python users!)

Other Key Words

print

The key word print writes a single argument to stdout with a trailing line break.

bye

The key word bye exits Shiny.

type

The key word type takes a single argument and returns the data type as a string.

> x: 42
> type x
number

with

with allows an object's scope (remember, just a closure) to be re-entered directly after creation and without using a method, and a block of method calls to be made rapidly:

print with 'abcde'
    alter 'c' '_'
    upper 0 1
end
Ab_de

Above, with took the literal string object abcde, executed its alter and upper methods, and returned the modified result.

Other Libraries

io

The io library exists to do simple I/O.

time

The time library exists to work with dates and times. All methods assume a YYYY-MM-DD HH:II:SS string format for dates. Shiny does not use Unix timestamps internally, so dates are not limited to the Unix epoch.

System Calls

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