Sushiscript is programming language transpiling to GNU Bash and aimed to provide a clean syntax for shell users.
- linux or unix OS
- conan
- cmake (3.5 or higher)
mkdir build && cd build
# for ubuntu, mac os do not need "-s compiler.libcxx=libstdc++11"
conan remote add bincrafters https://api.bintray.com/conan/bincrafters/public-conan
conan install .. -s compiler.libcxx=libstdc++11 --build=missing
# cmake and build
cmake .. && make install
sushiscript
is implemented mostly in C++14
and make a few uses of boost::optional
, boost::variant
and various utility functions in boost
, like format
and join
.
All sources are located in src/
, include/
and test/
. The structure of include/
shows the structure of modules, and although src/
does follow the top level module structure, it doesn't really distinguish the source files of submodule in a certain module.
Except for testing sources, all header files (*.h
) are under include/
, all source files (*.cpp
) are under src/
And here are the source files (directories) related to major parts of sushiscript
.
- Frontend (lexer & parser)
{include, src}/sushi/lexer/
{include, src}/sushi/parser/
include/sushi/ast/
- AST Analyze (scoping & type checking)
{include, src}/sushi/scope/
{include, src}/sushi/type-system/
include/sushi/ast/
- Code Generation
include/sushi/type-system/type.h
include/sushi/scope/scope.h
{include, src}/sushi/code-generation/
include/sushi/ast/
- Main
{include, src}/pipeline/
src/sushi/main.cpp
Here we take a quick tour over sushiscript
's basic syntax. For detailed information, consult language specification
# this is comment
1; 100; 0 # integer
"hello world" # string
true; false # boolean
./hello/world # relative path
/hello/world # absolute path
'a'; 'b'; # character
stdin; stdout; stderr # file descriptor
<unary op> 1 # <unary op> is +(abs value), -(negate)
1 <arith op> 1 # <arith op> is +, -, *, //(int division), %(mod)
1 <rel op> 1 # <rel op> is >, <, <=, >=, ==, !=
"hello " + "world" # concatenation
"hi " * 4 # "hi hi hi hi "
"hi " <rel op> "hello" # lexical comparison
"hello world"[0] # indexing
./hello // ./world # ./hello/world
/hello // ./world # ./hello/world
/hello // /world # ERROR, rhs has to be relative path
! echo "hello world"
{1, 2, 3} # array of int
{"hi", "world"} # array of string
{"hello", 123} # ERROR, only homogeneous array allowed
{{1, 2}, {5, 6}} # ERROR, nested array not allowed
{1, 2, 3, 4}[0] # indexing
{1: 2, 3: 4} # map from int to int
{"haha": 1, "hihi": 2} # map from string to int
{1: {1, 2, 3}} # ERROR, cannot map to/from array or map
{"ha": 1, "hi": 2}["ha"] # indexing
() # unit
Bool, Char, Int, Bool
Fd # file descriptor
Path # absolute Path
RelPath # relative path)
ExitCode
Array Int # array of Int
Map Int Int # map from int to int
define a: Int = 1
define b: String = "hahaha"
define c: Array Int = {1, 2, 3}
define d = ./hello/world # deduced d: RelPath
# definition
define Add(a: Int, b: Int, c: Int): Int =
return a + b + c
define Hello() = ! echo "hello"
# call
define sum = Add 100 200 300
Hello() # calling function with no parameter
# assign to variable
define a = 1
a = 2
# assign to indexing
define b = {1, 2, 3}
define c = "hello"
b[2] = 2
c[0] = "H"
if 1 < 2:
! echo "one less than two" # indent new block
else if 1 > 2:
! echo "one greater than two"
else: ! echo "one equal to two" # or same line
# command as condition
if ! find some file:
echo "file found!"
# or...
define success = ! find some file
if success: echo "file found!"
define a = 1
switch a + 1
case 1:
! echo "one plus one is one"
case 2:
! echo "one plus one is two"
default:
! echo "one plus one is else"
define a = 0
for a < 1024: # with only loop condition
a = a + a
for i in {1, 2, 3, 4}: # array based range loop
a = a + i
for true:
if a == 2: continue
if a > 1024: break
a = a + a
define name = "Sushi"
define a: String = "hello ${name}" # interpolation
define b: String = "say ${"hello ${name}" + "!"} # nested interpolation
# interpolation also worked in...
define c: Path = /hello/${name}
define d: RelPath = ./hello/${name}
! echo hello name # hello name
! echo hello ${name} # hello Sushi
# redirecting command, note the ',' after command
! cat somefile, redirect to ./another/file
! cat, redirect from ./input-file, to ./output-file
! echo hello, redirect to ./out
# grabbing command output, "here" is a keyword
define content: String = ! cat ./out, redirect to here
# function calls are redirectable, but no need for ','
define f() = ! echo "hello"
f() redirect to ./out
! find . | ! sort | ! xargs cat
function call | ! sort | anotherfunction call