{
"command": {
"symbol": "print",
"args": "Hello, World!"
}
}
brew install JunNishimura/tap/JSOP
go install github.com/JunNishimura/jsop@latest
Download exec files from GitHub Releases.
Since REPL is not provided, you can write your program in any file and pass the file path as a command line argument to execute the program.
jsop ./path/to/file.jsop.json
- Everything is an expression.
- Only
.jsop
and.jsop.json
are accepted as file extensions.
Integer value is a sequence of numbers.
Example
123
String value is a sequence of letters, symbols, and spaces enclosed in double quotation marks.
Example
"this is a string"
Boolean value is either true
or false
.
Example
true
Arrays are composed of expressions.
Example
[1, "string", true]
Strings beginning with the $
symbol are considered as identifiers.
Example
"$x"
Embedding the Identifier in a string is accomplished by using curly brackets.
Example
"{$hello}, world!"
To assign a value or function to an identifier, use the set
key.
parent key | children key | explanation |
---|---|---|
set | declaration of assignment | |
var | identifier name | |
val | value to assign |
Example
[
{
"set": {
"var": "$x",
"val": 10
}
},
"$x"
]
Functions can be defined by using set
key and lambda
expression`.
parent key | children key | explanation |
---|---|---|
lambda | declaration | |
params | parameters(optional) | |
body | body of function |
Example
{
"set": {
"var": "$add",
"val": {
"lambda": {
"params": ["$x", "$y"],
"body": {
"command": {
"symbol": "+",
"args": ["$x", "$y"]
}
}
}
}
}
}
Functions can be called by using command
key.
parent key | children key | explanation |
---|---|---|
command | declaration of function calling | |
symbol | function to call | |
args | arguments(optional) |
Example
{
"command": {
"symbol": "+",
"args": [1, 2]
}
}
Builtin functions are as follows,
関数 | explanation |
---|---|
+ | addition |
- | subtraction |
* | multiplication |
/ | division |
% | modulo |
! | negation |
&& | and operation |
|| | or operation |
== | equation |
!= | non equation |
> | greater than |
>= | greater than equal |
< | smaller than |
>= | smaller than equal |
print to standard output | |
len | length of array |
at | access to the element of array |
Conditional branches can be implemented by using the if
key.
parent key | children key | explanation |
---|---|---|
if | declaratoin of if | |
cond | condition | |
conseq | consequence(the program to execute when cond is true) | |
alt | alternative(the program to execute when cond is false) |
Example
{
"if": {
"cond": {
"command": {
"symbol": "==",
"args": [1, 2]
}
},
"conseq": {
"command": {
"symbol": "+",
"args": [3, 4]
}
},
"alt": {
"command": {
"symbol": "*",
"args": [5, 6]
}
}
}
}
Iterations are handled by using the loop
key.
parent key | children key | explanation |
---|---|---|
loop | declaration of loop | |
for | the identifier for loop counter | |
from | the initial value of loop counter | |
until | loop termination condition (break when loop counter equals this value) | |
do | Iterative processing body |
Example
{
"loop": {
"for": "$i",
"from": 0,
"until": 10,
"do": {
"command": {
"symbol": "print",
"args": "$i"
}
}
}
}
You can also perform a loop operation on the elements of an Array. Unlike the example above, the in
key specifies an Array.
Example
[
{
"set": {
"var": "$arr",
"val": [10, 20, 30]
}
},
{
"loop": {
"for": "$element",
"in": "$arr",
"do": {
"command": {
"symbol": "print",
"args": "$element"
}
}
}
}
]
Also, insert break
and continue
as keys as follows.
[
{
"set": {
"var": "$sum",
"val": 0
}
},
{
"loop": {
"for": "$i",
"from": 1,
"until": 15,
"do": {
"if": {
"cond": {
"command": {
"symbol": ">",
"args": ["$i", 10]
}
},
"conseq": {
"break": {}
},
"alt": {
"if": {
"cond": {
"command": {
"symbol": "==",
"args": [
{
"command": {
"symbol": "%",
"args": ["$i", 2]
}
},
0
]
}
},
"conseq": {
"set": {
"var": "$sum",
"val": {
"command": {
"symbol": "+",
"args": ["$sum", "$i"]
}
}
}
},
"alt": {
"continue": {}
}
}
}
}
}
}
},
"$sum"
]
Use return
key when you exit the program with return.
[
{
"set": {
"var": "$f",
"val": {
"lambda": {
"body": [
{
"set": {
"var": "$sum",
"val": 0
}
},
{
"loop": {
"for": "$i",
"from": 1,
"until": 11,
"do": {
"if": {
"cond": {
"command": {
"symbol": ">",
"args": ["$i", 5]
}
},
"conseq": {
"return": "$sum"
},
"alt": {
"set": {
"var": "$sum",
"val": {
"command": {
"symbol": "+",
"args": ["$sum", "$i"]
}
}
}
}
}
}
}
}
]
}
}
}
},
{
"command": {
"symbol": "$f"
}
}
]
Macro can be defined by using defmacro
key.
parent key | children key | explanation |
---|---|---|
defmacro | declaration of macro definition | |
name | name of macro | |
keys | keys | |
body | the body of macro |
You can also call the quote
symbol for quoting, and unquote by adding backquotes to the beginning of the string.
Example
{
"defmacro": {
"name": "unless",
"keys": ["cond", "conseq", "alt"],
"body": {
"command": {
"symbol": "quote",
"args": {
"if": {
"cond": {
"command": {
"symbol": "!",
"args": ",cond"
}
},
"conseq": ",conseq",
"alt": ",alt"
}
}
}
}
}
}
Defining function can be much simpler if you use Macro.
Example
[
{
"defmacro": {
"name": "defun",
"keys": ["name", "params", "body"],
"body": {
"command": {
"symbol": "quote",
"args": {
"set": {
"var": ",name",
"val": {
"lambda": {
"params": ",params",
"body": ",body"
}
}
}
}
}
}
}
},
{
"defun": {
"name": "$add",
"params": ["$x", "$y"],
"body": {
"command": {
"symbol": "+",
"args": ["$x", "$y"]
}
}
}
},
{
"command": {
"symbol": "$add",
"args": [1, 2]
}
}
]
Comments can be inesrted by using //
key.
Example
{
"//": "this is a function to add two values",
"set": {
"var": "$add",
"val": {
"lambda": {
"params": ["$x", "$y"],
"body": {
"command": {
"symbol": "+",
"args": ["$x", "$y"]
}
}
}
}
}
}
Finally, I have included an example of solving a FizzBuzz problem in JSOP.
Example
[
{
"set": {
"var": "$num",
"val": 31
}
},
{
"loop": {
"for": "$i",
"from": 1,
"until": "$num",
"do": {
"if": {
"cond": {
"command": {
"symbol": "&&",
"args": [
{
"command": {
"symbol": "==",
"args": [
{
"command": {
"symbol": "%",
"args": ["$i", 3]
}
},
0
]
}
},
{
"command": {
"symbol": "==",
"args": [
{
"command": {
"symbol": "%",
"args": ["$i", 5]
}
},
0
]
}
}
]
}
},
"conseq": {
"command": {
"symbol": "print",
"args": "{$i}: FizzBuzz"
}
},
"alt": {
"if": {
"cond": {
"command": {
"symbol": "==",
"args": [
{
"command": {
"symbol": "%",
"args": ["$i", 3]
}
},
0
]
}
},
"conseq": {
"command": {
"symbol": "print",
"args": "{$i}: Fizz"
}
},
"alt": {
"if": {
"cond": {
"command": {
"symbol": "==",
"args": [
{
"command": {
"symbol": "%",
"args": ["$i", 5]
}
},
0
]
}
},
"conseq": {
"command": {
"symbol": "print",
"args": "{$i}: Buzz"
}
},
"alt": {
"command": {
"symbol": "print",
"args": "$i"
}
}
}
}
}
}
}
}
}
}
]
JSOP is released under MIT License. See MIT