Grits
Grits (Generally Ridiculous In Terms of Scope) is an interpreted programming language created by Davie Janeway in 2009.
Overview
Generally speaking, Grits is a fairly subservient language with applications in Rapid Application Development and prototyping. The interpreter will only accept one comment/statement/declaration/command etc per line. Whitespace is included at the user's peril.
Development Cycle
Grits is currently in alpha/beta development. The current build is v0.7. New functionality is added to the language core in every build, pre version 1.0. There is no backwards compatibility between builds.
Comments
Anything enclosed in reverse angle brackets is considered to be a comment by the interpreter.
>This is a comment<
Grits does not support in-line or multi-line comments.
Variables
Variables are 'duck' / dynamically typed. The declaration operator is %, the assignment operator is .. A variable must be assigned a value upon declaration. Upon release, Grits v1.0 will support the following primitive types:
int
%i.99
String
%s.'Hello, World!'
boolean
%bool.t %bool.f %bool.(boolean expression)
byte
%b.*101
float
%fl.1.0f
A variable can be reassigned to any type
some_int.'This variable is now a string'
Arrays
Arrays in Grits are zero-indexed and may contain Variables / values of any type. The following example shows how to initialise an Array:
%arr.[1 2 3]
An Array's elements are accessed in the following way:
arr_0
Where arr is the name of the Array and 0 is the element's zero-indexed position. An Array's length is accessed by replacing the element position with an asterisk.
arr_*
Meta-Variables
One of Grits' main / most esoteric features is the ability to store and protect the value of a variable in a special 'meta' variable. To initialise the meta-int, use the following syntax:
%some_int.99 [some_int] :$
This example stores the value of some_int in the meta-int and then prints the value of the meta-int to the console. The meta-string is intialised in much the same way:
%some_string.'This is a string' (some_string) :^
Arithmetic
When applied to integers, the following examples are all valid expressions:
(2+2) (2-2) (2*2) (2/2) %var.2 (var+2) (var-var) (var*2) (2/var)
String Functions
The four mathematical operators mentioned above can also be applied to Strings.
{'Hello,'+'World!'} results in 'Hello,World!' {'Hello'-'H'} results in 'ello' {'Hello99'*'\d'} results in 'Hello', matches and removes Regex strings {'Hello99'/'\d'} results in t, matches Regex strings, returns a boolean
Loops
Grits features two types of logic gate, TERNARY IF and WHILE NOT.
TERNARY IF
%int.99 ?int.0{:'true'|:'false'}
A Grits TERNARY IF statement tests the left value (int) against the right (0). If the test equates to true, the left command (:"true") is executed, if false, the right command (:"false") is executed.
WHILE NOT
%int.99 ??int.0{:(int-1)}
A WHILE NOT loop test the left value (int) against the right (0), if true, the loop breaks. If false, a single command (:&int{-|1})is executed, ad infinitum until left value == right value. NOTE: If the command parameter never results in left value == right value, the loop will never end!
Functions
Function declarations and calls are made with the ! operator. When called, a function executes an arbitrary number of space-delimited commands.
%int.100 %str.'Hello, World!' !Test{ :int :str } !Test
The use of parameters is only possible in Grits v0.7+. Parameters are used in the following way:
!sqr { :(.x*.x) }
The keywords .x .y .z .X .Y .Z are currently reserved as placeholders for parameters. When the function is called, .x will be replaced by parameter 1, .y with parameter 2 ... .Z with parameter 6. As of v0.7, the maximum number of parameters a function may accept is limited to 6. Using our sqr function, we can pass in a parameter using the <- (Inject) operator:
!sqr <- 9
In pseudo-code, the sqr function could be expressed as:
function sqr (int n) { print n*n; }
A call to this function would resemble:
sqr(9);
NOTE: It is currently impossible to escape whitespace characters in Grits. The function:
!Test{:'Hello, World!'} !Test
would actually result in the interpreter trying to execute :Hello, and World! as separate commands!
Return Values
As of Grits v0.7, it is possible for functions to return values using the -> (Eject) operator.
!sqr { ->(.x*.x) } >Function sqr returns (1st param * 1st param)< %square_of_nine.!sqr <- 9
Recursive Functions
It is entirely possible to construct recursive functions in Grits. Consider the following code:
%i.10 !R{ :(i-1) ?i.0{:'END'|!R} } !R
The function R prints the result of int - 1 then tests to see IF int == 0. If it does, print "END" to the console. If not, R runs again, ad infinitum.
Self-Modifying Functions
It is also possible to write self-modifying functions.
%i.99 !Mod{ :(i-1) ?i.0{'Done'|!Mod} !Mod{:(i+1)}} !Mod
In this example, we create a function Mod whose commands(in pseudo-code) are:
var i = 99; function Mod() { print i; IF (i == 0) THEN (print 'Done') ELSE function Mod() { print i+1; } }
WARNING: This function does not contain an escape clause and will run infinitely (at least on an unbounded machine)
Inject / Eject
Grits v0.7+ features two new operators, <- (Inject) and -> (Eject). The operations they perform depends upon the context in which they are used. Possible uses are (or at least will be in future builds):
>Import / Packaging (Grits Application Packages are in active development)< -> Test.gap <- Test.gap
>Passing / returning values into / from Functions (see Functions)< !sqr { ->(.x*.x) } !sqr <- 10
>Streams (e.g File I/O)< %some_file.'C:\Path\test.txt' >Read first byte into Variable b< %b.<- some_file *1 >Write to file< some_file -> 'Hello, File!'
>Push / Pop operations on Arrays< %arr.[1 2 3] arr <- 4 arr -> 2
Includes
To import the functions and variables from one Grits file to another, use the @ symbol followed by the absolute path of the file you wish to include. Because of Grits universal global scope, anything declared / initialised / defined in the included file is accessible in the including file. The following example shows code form two files, testlib.g and uselib.g
testlib.g
%str.'Hello, World!' !Hello{:str}
uselib.g
@absolute_path/testlib.g !Hello
In testlib.g, the function Hello is defined. In uselib.g, testlib.g is imported and its Hello function is called. The result is "Hello, World!" printed to the console.
Interactive Mode
As of v0.6, Grits can be run in interactive mode (similar to python). Consoles are called from files with
===
symbol.
Self-Redefinition
As of v0.6, Grits is a self-defining language. Any keyword/symbol can be redefined by the user. The following example redefines the : keyword (output) as print
:'Regular Output Symbol' ~:;print print 'Redefined Output Symbol'
The ~ command takes two parameters (separated by a semi-colon). Parameter 1 must be an existing keyword and will redefined as parameter 2.
Current Implementation
The Grits Project is currently hosted at Sourceforge and Project Kenai. The interpreter is written in Java.