https://github.com/zeroxthreef/simpletinyscript
A somewhat small experimental scripting language
https://github.com/zeroxthreef/simpletinyscript
Last synced: 11 months ago
JSON representation
A somewhat small experimental scripting language
- Host: GitHub
- URL: https://github.com/zeroxthreef/simpletinyscript
- Owner: zeroxthreef
- License: unlicense
- Created: 2020-06-18T11:29:19.000Z (almost 6 years ago)
- Default Branch: master
- Last Pushed: 2023-08-19T23:07:46.000Z (almost 3 years ago)
- Last Synced: 2025-03-28T00:47:00.123Z (about 1 year ago)
- Language: C
- Size: 183 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# SimpleTinyScript
STS is an experiment in trying to make a really tiny scripting language that is still mostly usable in an environment where it is embedded in another project.
The code quality for this is not near acceptable. This project is not meant for any serious use.
```
import stdlib.sts
global i 0
loop(< $i 10) {
print hello world
++ $i
}
```
## Usage (when compiling cli.c)
`./sts` to enter repl. Works like a shell and will fall back on using the native shell if no global or local function is found
`./sts file.sts` to eval a script
## Configuration Definitions
```
#define STS_GOTO_JIT //enable the goto jit which requires a gcc extension
#define CLI_ALLOW_SYSTEM //allow the system() shell function to be used in last resort
#define INSTALL_DIR "/path/to/install" //change the install directory so imports work in cli.c
#define CLI_NO_SOCKETS //remove the ability to use sockets
#define CLI_NO_TLS //remove the ability to have tls sockets. Will already be in effect if there are no sockets
```
## Libraries Used
The core of sts lives in ``simpletinyscript.h`` which only depends on the C standard library. However, ``cli.c`` depends on system libraries and on the following public domain libraries which exist in ``ext/``:
* [pdjson](https://github.com/skeeto/pdjson)
* [zed_net](https://github.com/mackron/zed_net)
* [Monocypher](https://github.com/eduardsui/tlse)
* [tlse](https://github.com/LoupVaillant/Monocypher)
* [base64](https://github.com/badzong/base64)
## Documentation
**print ...**
turns all values into printable strings and adds spaces between them. Also appends a newline and prints it to stdout
**pass var**
passes the value in 'var'. Useful when replacing 'return'
**string ...**
same as ``print``, but adds no spaces and no newline
**global varname (value_to_set)**
adds a variable of 'varname' to the global scope. Will return 1 or 0 if it exists when no value_to_set is passed
**local varname (value_to_set)**
same as ``global`` but works in the local scope (global scope if not in any function)
**string-hash var**
returns a numeric hash of the string using FNV-1a
**const var**
marks the value as readonly
**typeof var**
returns a number of STS_* for the type declared in an enum
**sizeof var**
returns a number set to the size of the value passed
**if cond eval_expr**
tests if the cond is recognized as true and evaluates eval_expr if so. Returns a 1 or 0 if it ran
**elseif cond eval_expr**
same as ``if`` but will not do anything if the previous value is 1
**else eval_expr**
only evaluates eval_expr if the previous value is not 1
**function name (parameters) eval_expr**
2 major cases:
1. if 'name' is nil, then it is not automatically added to the current local scope
2. if 'name' is a string, it is added to the local scope automatically
requires 0 or more parameters. The last argument is always the eval_expr.
this always returns the function value regardless of a nil name
**copy var**
recursively copies the value passed
**self-name**
retrieves the script filename from the AST
**number var**
turns a string value into a number
**asc number**
returns a string consisting of the ascii character equal to 'number'
**char string index**
returns the numeric value of the character in 'string' at position 'index'
**get var index**
returns the value in 'var' at 'index'. Only works on arrays and strings
**set val_to_set val_to_shallow_copy**
shallow copies 'val_to_shallow_copy' and overwrites 'val_to_set' with the new value
**array ...**
returns an array of 0 or more values passed
**remove var index**
removes the value in 'var' at position 'index'. Only works on arrays
**insert var index insert**
inserts 'insert' into 'var' at position 'index'. only works on arrays
**replace var index insert**
replaces instead of shallow copies the value at an array index
**import file**
look for file relative to the interpreter PWD, and if it cant find the file and compiled with cli.c, it will search the system install directory
**call function ...**
calls function value 'function' and supplies arguments from '...'
**&&**, **||**
work just like in C
**==**, **!=**, **<**, **<=**, **>**, **>=**
work just like in C, but let you do string comparisons too. Need to be the same type
**+**, **-**, **\***, **/**, **\*\***, **%**, **>>**, **<<**, **&**, **^**, **|**, **~**, **!**, **++**, **--**
work mostly just like C, but bit operations conver numbers to integers internally then back to doubles. ``**`` is exponential. ``++`` and ``--`` are prefix only
**C's math.h trig functions**
mostly all present
The following functions are if embedding into cli.c
---
**pipeout var \*command\***
runs popen() and the stdout from the command provided is sent to 'var' as a string. The return value is the return value of the command. This uses the native shell
**file-read file**
returns nil if not found, and a string of the file's contents
**file-write file string**
returns nil if file doesnt exist and the number of bytes written from 'string' if it does
**file-append file string**
same as ``file-write`` but appends to the file instead of overwrites
**stdin-read number_or_char**
2 possible options:
1. if 'number_or_char' is a number and equal to 0, it will read until EOF in stream and if >0, it will read until the size of the buffer reaches this
2. if 'number_or_char' is a single width string, the character will be tested and read until encountered in the stream
**stdout-write ...**
similar to ``print`` but no spaces between values and no newline and prints to stdout
**stderr-write ...**
same as ``stdout-write`` but to stderr instead
**getenv name**
returns nil if not found or a string of the environment variable
**setenv name value**
sets the environment variable to the value if found or makes a new variable of that name
**sleep seconds**
sleeps for the number of seconds provided in 'seconds'
**json string_data|any_value (prettify)**
if supplying a single string argument, it will parse the string. Two arguments with a number is json from value conversion. ``$prettify`` as 1 will make the output look nice. 0 will make the output compact
**socket-tcp port non_blocking listening**
creates a tcp socket, and if creating a server socket, set listening to 1
**socket-udp port non_blocking**
creates a udp socket
**socket-set-broadcast socket state_0_or_1**
apply SO_BROADCAST
**socket-tcp-connect socket host port**
connect to a tcp server with the supplied arguments. Returns 1 if the address is unknown, 2 if the host didnt connect, and 0 if successful
**socket-tcp-send socket data**
sends string buffer to host. Returns the amount of sent bytes or -1 on error
**socket-tcp-recv socket**
returns a string buffer if successful, -1 on error, or 1 if the socket would block on a nonblocking port
**socket-udp-send socket destination_address destination_port data**
sends string buffer to host. Returns the amount of sent bytes or -1 on error
**socket-udp-recv socket**
returns a string buffer if successful, -1 on error, or 1 if the socket would block on a nonblocking port
**socket-tcp-would-block socket**
returns 1 if the socket would block
**socket-tcp-accept socket out_client_socket_reference**
the out_socket_client_reference value will be set to the client socket (similar to pipeout) and returns 0 upon success, 1 upon would block, -1 upon error, and 2 upon the socket not able to listen
**socket-enable-ssl-client socket**
enable ssl on the current socket. Returns nonzero on error
**crypto-argon2i password_str salt_str block_num iteration_num**
returns a 32 byte string. Monocypher documentation recommends 100000 blocks and 3 iterations
**crypto-hash str**
returns a 32 byte string hash using blake2b
**crypto-sign-public privkey_str**
returns a 32 byte public key string. Requires a 32 byte private key string
**crypto-sign message_str privkey_str**
returns a 64 byte signature string. the private key string must be 32 bytes
**crypto-check message_str signature_str pubkey_str**
returns 1 if a correct 64 byte signature str is used for the 32 byte public key str on the message
**base64-encode str**
return a b64 encoded string
**base64-decode str**
return a decoded b64 string
**exit status**
exits the interpreter with an optional status
**directory-list**
returns an array of strings in the directory or nil if it doesnt exist
**platform**
returns 'windows' or 'unix'
The following functions are documentation for ``stdlib.sts``
---
**STS_EXTERNAL**, **STS_NIL**, **STS_NUMBER**, **STS_STRING**, **STS_ARRAY**, **STS_FUNCTION**
returns the number of the type returned by ``typeof``
**hashmap ...**
returns a hashmap of "key, value". To make easily readable, append a '\' at the end of every key and value passed so the function arguments cascade vertically
**hashmap-get map key**
returns nil if not found and the value in 'map' of 'key'
**hashmap-exists map key**
returns 1 if the key does and 0 if not
**hashmap-set map key value**
sets the key if it exists, and if it doesnt it will make a new one to set to 'value'
**hashmap-replace map key value**
replaces the entire row value and key if it exists, and if it doesnt it will make a new one to set to 'value'
**hashmap-remove map key**
removes 'key' and its value from 'map'
**hashmap-keys map**
returns an array of the strings used as keys in the hashmap
**hashmap-values map**
same as ``hashmap-keys`` but for the values instead
**hashmap-update map**
because keys are passed by reference and stored in the row rather than copied into the row, the key could change at some point and thats mostly ok, but the string hash needs to be updated as well. Call this if theres a possibility that the keys updated in the hashmap
**string-tokenize string token**
returns an array of the string separated into smaller strings divided by 'token'
**string-combine array between_string**
undoes ``string-tokenize** if passed the same token string
**string-range string start end**
returns an inclusive substring from 'start' and 'end'
**string-search string needle**
returns -1 if not found, and the position in the string where 'needle' is first found
**string-rsearch string needle**
same as ``string-search`` but searches from the back of the string
**string-insert string position instring**
returns a new string with the instring between 'string' at 'position'. Works at the end of the string as well
**string-remove string position**
returns a new string with the character at 'position' removed
**string-replace string replacee replacement**
returns a new string with 'replacee' replaced with 'replacement' everywhere
**getpwd self**
returns the pwd when ``self-name`` is passed
**relimport self script**
imports and uses ``getpwd`` internally when passed ``self-name`` in 'self'
**stdlib-get-error**
returns nil if no error, and the string of the current stdlib error
**stdlib-set-error component_str error_str**
sets the current stdlib error to the format "component_str: error_str"
**string-value-print value**
returns a string of recursively created stringification of 'value'
**typeof-string value**
returns a string of the type instead of a number. Looks like "STS_NUMBER"
**expr ...**
!WIP
**enum ...**
!WIP
**+=**, **-=**, **\*=**, **/=**, **%=**, **\*\*=**,
work like C's operators, but ``**=`` is exponential equal
## License
Unlicense. This project is released into the public domain.