"hello world" :: Str
true :: Bool
false :: Bool
5 :: IntBarewords:
$ five
five :: File
$ let five = 5
$ five
5 :: Int
$ five.*
[] :: [File]- A bareword is a file literal, unless it has been declared as a variable with
let. - A bareword that contains wildcards is a glob literal, typed as a list of files.
Function literals:
$ let f = \x y -> y
$ :type f
'a -> 'b -> 'b- To be written.
$ (1, [])
(1, []) :: (Int, ['a]) | Heterogeneous | Variable length
--------------:|:---------------:|:-----------------:
Integer keys | Tuple | List
Complex keys | Record* | Dictionary*
Why isn't there a heterogeneous, variable length container? That would require runtime type information, which is currently beyond the scope of Tush.
* Not implemented yet.
To be written.
(++) :: ['a] -> ['a] -> ['a]- Joins two lists. Strings are not (yet) lists.
(|), (|:)- To be written.
let <var> = <expr>let defines a variable, shadowing any previous variables of the same name.
size :: File -> Int- Returns the size, in bytes, of a file.
zipf :: ('a -> 'b) -> 'b -> ('a, 'b)- Zips up a function result with the argument the produced it.
- An example:
$ let sz = size zipf
$ type.h sz
(2434, type.h) :: (Int, File)
$ type* | sz
848 type-internal.h
9693 type-unify.c
11546 type.c
2434 type.h
:: [(Int, File)]sort :: [(Int, 'b)] -> [(Int, 'b)]- Sorts a table by its first column in ascending order.
- Currently it only sorts on
Int. In the future it will be more general. - Continuing the example above:
$ type* | sz | sort
848 type-internal.h
2434 type.h
9693 type-unify.c
11546 type.c
:: [(Int, File)]sum :: [Int] -> Int- Sums a list.
$ type* | size | sum
24521 :: Int:type <expr>
:ast <expr>
:cd <dir>
These are special commands available from the prompt, all of which take expressions. They are not part of the language and therefore can't be used within other expressions.
:typedisplays the type of an expression without evaluating it.:astdisplays the Abstract Syntax Tree of an expression with types, again without evaluating it.:cdchanges the working directory to the the result of the expression given, which must be of typeFile. It does not evaluate it if otherwise.
cd is not part of the language because it's the directory equivalent of goto. The only reason to indefinitely enter a directory is when at the prompt, where one might not know how long they want to stay there. See into below for a structured way to change directory.
$ [*.[ch]]
main.c main.h
:: [File]
Note how the outer brackets are tokens of their own, opening and closing a list, while the inner brackets are part of a glob. After the opening bracket, the lexer waits for a closing bracket before moving onto the next token.
The basic rules for tokens are:
- Whitespace, parentheses (
()) and backticks (`) delimit universally. - If a token starts with an opening bracket (
[{) or!then it immediately ends there. - Closing brackets (
]}) are delimiters, unless they match a bracket in a glob. - Commas are also delimiters, but will be escaped by an open glob bracket.
- Nothing else delimits.
This is designed to do the reasonable and intuitive thing.
[name1, name2, name3]is a list of files, the commas and brackets are not part of the filenames.*.{cpp,h}is an alternation glob.
$ :type {field: <expr>}
{field: <type of expr>}
$ :type [key: value]
<type of key> <type of value> Dict
if <expr>:
elif <expr>:
else:
for <var>, <iterable>:
switch <expr>
case <pattern>:
into <dir>:
make-into <dir>:
<fn> <args..>:
<stmts..>
<macro>! <args..>: