Scrip7

From Esolang
Jump to navigation Jump to search

Scrip7 is a language created by Oren Watson on 2014 November 22. It can be described as a low-level scripting language. It was originally designed for creating and manipulating data structures inside a C program. It is quite good at doing this, so long as the programmer is very good at pointer arithmetic. The reference implementation for the first version was finished November 24. The interpreter and language are still in primary development. The interpreter is written as a function which can be called to operate at any point in a C program, but the source also includes a "main" function for a standalone interpreter.

Scrip7 was originally named because it looks cool (in the author's juvenile opinion) and the first version of the idea had seven registers in all 8 forms, and the author forgot that the alphabet has 26 letters, not 28. The purpose of scrip7 is not really for standalone programs, but as an unconventionally powerful serialization format, configuration file format, debugging interface, or scripting language for C programs.

Syntax

A scrip7 program is a string of characters. It consists of statements, matched parentheses, and the symbols ` (end) $ (skip) and # (stop). Statements consist of a one-letter register name followed by an optional integer offset, a one-character operator, and either another register or a literal (either integer, string, character, or floating-point). Spaces are allowed anywhere except inside a numeric literal and are ignored. In other words, a simple statement is e.g. a + b or x+6.7.

Curly brackets represent a construct similar to the C if(0)while(1){}. Square brackets are used to provide loop labels that do not jump, so that [..} is similar to C while(1){...} and {...] is similar to C if(0){...}

Variables/Registers

The scrip7 language has 8 registers of pointer type, whose notation varies according to the type of data accessed through them, as well as having a special notation by which the pointer's address is modified directly.

Datatype: int8 int16 int32 int64 float double void* addr
reg. 0     a     A     i     I     u     U     o     O
reg. 1     b     B     j     J     v     V     p     P
reg. 2     c     C     k     K     w     W     q     Q
reg. 3     d     D     l     L     x     X     r     R     
reg. 4     e     E     m     M     y     Y     s     S
reg. 5     f     F     n     N     z     Z     t     T
reg. 6     g                                         G
reg. 7     h                                         H
null       _     _     _     _     _     _     _     _

The normal registers start off all pointing to the beginning of a section of memory. In the standalone interpreter this memory is 1000 bytes of blank memory, but it could instead be some sort of data structure that the host program wants the script to "run on". The null register is only valid on the lefthand side of a statement, and indicates that the value is to be thrown away. A register name may be followed by an offset which is an intger preceded by either a '(' or ')' character. The offset is added to the address, either in bytes if it is '(' or in units the size of the pointed object if ')'.

The G or sixth register is special as it is the instruction pointer. When G hits a curly bracket from the outside, it skips to after the end. When G hits a curly bracket from the inside, it skips to the beginning. When G hits a $ it skips to after the #. Various statements can also trigger a skip. Otherwise, G moves forward, executing statements as it goes. Thus, brackets {} are used for both loops and comments. $ and # could also be used for comments. The program ends at end of file or when it hits a backquote.

Semantics

Literals are in the following forms:

a='a   {character}
Q={lsklsk}  {code string pointer that points directly into the code memory}
Q=5"sadsd {creates a zero-ended string in heap memory. does not use escapes, because it is a "Hollerith encoding"}
I=22312 I=0%fffff5ed {integer}
X=8.321^3 x=355/113 {floating point}

The following operators typically exist:

α=β set α to β
αzβ swap α and β
αpβ print β to stream given by α. _ is stdout
αxβ print β in hex to stream given by α. _ is stdout
αrβ read in a line from stream given by β and put value in α
αSβ copy N objects from β to α, if β is an address. (N being the register N of course) otherwise, set N objects in α to the value of β.
αLβ get number of objects in α until the value of β is reached. set N to it. 
α\β undivide β into two consecutive values in α.
αRβ read N objects of α's type into α, from steem number β.
αWβ write N objects of α's type from α, to stream number β..
α.β put β as char, to stream indicated by α. _ is stdout.
α,β get char into α, from stream indicated by β.
α+β add β to α.
α-β subtract β from α.
α/β divide α by β
α%β modulo α by β
α*β multiply α by β
α|β bitor β into α
α&β bitand β with α
α^β raise α to β power
αcβ multiply α by cos β
αsβ multiply α by sin β
α_β multiply α by log β
αtβ multiply α by tan β
αaβ set α to atan(α/β)
αeβ multiply α by e^β
αXβ xor α with β
αMβ set α to point to β newly allocated bytes
αNβ resize allocated memory at α to β bytes.
α>β move α β objects forward
α:β set α to β and move α to next object
α;β  move to previous object and set α to β
α<β move α β objects backward
αFβ free memory at α
α~β skip to # if α != β
αgβ skip to # if α <= β
αlβ skip to # if α > β
α!β skip to # if α == β
αKβ save current place into α
αGβ goto place saved in β
αCβ call α as a void(*)(char**) with β as parameter.

Other operators may exist, providing extra functionality specific to the host program. The operators marked with * at the start of the description are not required to exist. (For example, a Windows host program might not provide console I/O.)

The operators are not guaranteed to do anything if the operation makes no sense for the data type.

Example

The following examples should help clarify how the parentheses, $, and # are supposed to be used.

{prints the fibonacci numbers up to 1000}
j>1 {point j to a different int from i}
i=0
j=1
[jpj i+j OzP {print j, add i to j, swap i and j pointers}
jl1000}# {loop only if j is less than 1000}
Q=14"Hello, World!
cL0cWN

An example of how scrip7 is meant to be used:

//in C code:
struct imageprop {char*filename;int cropwidth;int cropheight;double scale;} bgprop;
...
FILE *f=fopen("bgprop.s7","r");
if(f){scrip7f(f,&bgprop);
fclose(f);}
...
(in bgprop.s7 code)
o:11"starsbg.jpgi:250 i:500 U:2.2

External Resources

  • Hopefully getting stabler release in C: