xeh

0

Описание

Языки

  • Rust99,8%
  • Makefile0,1%
  • Остальные0,1%
6 месяцев назад
6 месяцев назад
6 месяцев назад
6 месяцев назад
6 месяцев назад
6 месяцев назад
README.md

What is XEH?

XEH is a dynamic, stack-oriented scripting language designed for live coding as well as a tool for binary data parsing and construction.

What make XEH interestig is ability to save snapshot, test something and rollback without restarting the whole program, just like a video game!

Building and Running

cargo build --release # command line options xeh [options] [sources] Options: -i path input binary file -e expression evaluate expression -r enable reverse debugging -h, --help print help # repl commands /trial switch to live coding mode /repl switch to REPL mode /snapshot snapshot program state /rollback rollback to the latest snapshot /next debugger - step forward /rnext debugger - step backward

Quick Language Reference

Comments

\ singleline comment \( multiline commet \)

Literals

\ decimal 7 -99 1_000 \ hex 0xff 0x11_EE \ binary 0b11111 0b1111_1111 \ real 2.78 -1.2e-5 \ string "escapes \\ \" \r \n \t"

Words

The whole program constist of words and literals. Depending on the definition word maybe function, variable or just an identifier.

  1. Words are separated by whitespaces.
  2. Word name consist of any characters, but can't start with digit or double quote.
\ valid words abc my-name +[] _"d^%$$$#112d'"d+" a0000-/-(22) .99 \ invalid words 0waa 9sss "abc

Functions

Function definition stats with

:
word, then function name and body follow, definition ends with
;
.

: hello "Hello!" println ;

Variable

Variable definition starts with

var
then name follow, initial value is taken from the stack.

\ define a new global variable 0 var counter \ update counter 10 -> counter

Locals

Local is a read-only binding visible only inside the function body. Initial value is taken from the stack.

\ locals : print2 local b local a "a = " print a println "b = " print b println ; 1 2 print2

Conditional execution

Y 0 <= if Y abs -> Y endif X 2 mod zero? if "even" else "odd" endif \ select one case of the multiple different choices X case 0 of "A" endof 1 of "B" endof \ fallback, drop unmatched value from the stack drop "Other" endcase

Basic loops

\ loop with pre-codnition, test condition before every iteration begin remain 5 > while read-more repeat \ post condition, restart loop if condition is false begin read-byte zero? until \ endless loop begin day-of-week "friday" == if \ break loop execution break then repeat

Counted loops

\ count from 0 to 10, current loop index is accessed with "I" 10 0 do I print loop \ outer loop index is accessed with J 10 5 do \ J 5 0 do \ I "J=" print J print "I=" print I print loop newline loop

Foreach loop

\ put next item on top of the stack, item index is "I" [ 1 2 ] foreach \ current item println \ current index I println loop \ Put every key and value on top of the stack { 1 2 } foreach println \ key println \ value loop \ Chars "abc" foreach println loop \ Bits |f0| foreach println loop

Tags

Tags is a custom property map sticked to the value but not directly accessible. Tags have no impact on using value and dissapear after value modification.

\ stick "abc" string to the integer 10 10 ^{ "ten" "name" ^} var X \ get "color" property X "color" get-tag println \ add color tag X "red" "color" insert-tag -> X \ show all tags X tags println X 1 + println

Meta evaluation and compilation

Source code execution operate in three modes:

* Compilation - source code translation to the virtual machine bytecode * Evaluation - execution of the generated bytecode * Meta evaluation - using the result of the source code execution as input for compilation

User is free to switch forth and back between the modes. When the compiler see the

#(
it switch to the meta mode, then execute code till the closing
#)
. All values on the stack are passed to the parent mode.

: fib dup 1 > if dup 2 - fib swap 1 - fib + endif ; \ compute Fibonacci number at compile-time (# 20 fib #) var fib-of-20

Constants

Constant is a read-only word that inline its value immediately without refering to the memory cell. Initial value is taken from the stack and must be defined inside of the meta mode.

#( 1.0 60.0 / const FRAME-TIME #)

Enums

Create enumerated list of constants.

enum MyEnum \ By default enumeration starts with zero. : A : B \ Use `=` to assign custom value to the field B 2 + = C endenum

Destructuring

let PATTERN

Ensure that each name in the PATTERN have corresponding value. Using literal instead of the name test that value is exactly match, otherwise error is raised.

\ bind 1 to a 1 let a \ test that a is 1 a let 1 \ raise error, when a not equal to 2 a let 2 \ bind vector elements [ [ 1 2 ] [ 3 4 ] ] let [ [ a b ] [ c d ] ] \ slice first two elements of the vector and bind remaining to the xs [ 1 2 3 5 7 ] let [ x1 x2 & xs ] \ find map keys { 1 "key1" [ 2 3 ] "key2" } let { "key1" x "key2" [ 2 y ] } \ split the value and tags 123 ^{ "red" "color" ^} let ^ all-tags val \ find tag property 123 ^{ 1 "a" 2 "b" ^} let ^ { "a" aval } val

Source code injection

Meta evaluation result might serve as input for compilation. When compiler see immediate word

~)
instead of the closing bracket, first compiler join result into a string and then treat that string as a part of the source code.

\ define variables from list #( [ "aa" "bb" "cc" ] foreach I " var " rot loop ~) bb println