SxScript
Embeddable scripting language for C# written in C#.
Install-Package SxScript
Hello world:
SxScript.SxScript script = new SxScript.SxScript();
string stdout = await script.Interpret("print \"hello world\"");
First 10 Fibonacci numbers, recursive:
function fib(n) {
if (n <= 1) return n;
return fib(n - 2) + fib(n - 1);
}
for (var i = 0; i < 10; i++) {
print fib(i);
}
// result: 0 1 1 2 3 5 8 13 21 34
Check https://github.com/lofcz/sxscript/tree/master/SxScriptTests/Programs for more programs.
Goals of this project are (in order of priority, desc)
- good test coverage
- support both adhoc evaluation and il bytecode + vm
- high IO throughput via async/await
- safe by default, require explicit whitelisting of CLR interop
- allow limitation of execution time, memory used, intructions executed, recursion depth, enumerables length, iterations in looping statements
- syntactically be a relaxed subset of C# (inclined towards Lua, JS)
- visitable AST
Progress tracker
- statements
- branching
- if
- else if / else
- ternary (a ? b : c)
- switch
- looping
- while
- for
- foreach
- jump
- goto
- break
- continue
- return
- labeled
- label
- case
- default
- scope
- code block {}
- global scope
- variable shadowing
- logical
- and / &&
- or / ||
- short circuit
- bitwise
- &
- |
- modifiers
- await
- async
- public
- private
- static
- base types
- function
- null / nill
- int
- double
- string
- bool
- object
- true, false
- array (hashmap)
- branching
- operators
- assignment
- unary +, -
- binary +, -, *, /, %, ^
- compound assignment +=, *=, /=, -=, %=, ^=
- null coalescing ??, ??=
- postfix
- ++, --
- arrays
- object members
- comments
- // single line
- /* */ multiline comment. nesting won't be allowed
- evaluation
- interpretation
- bytecode + vm
- OOP
- classes
- this
- constructors
- static methods
- access modifiers (public, private)
- inheritance
- polymorphism
- getters & setters
- traits
- FFI
- (partially) calling FFI functions, this should support both
Func<T1..T16>
+Action<T1..T16>
andFunc<Task<T1..T16>>
+Action<Task<T1..T16>>
- sugar
- default parameter values
fn sum(a = 1, b = 2) {}
- parameter by name
myFn(myParam: 1)
- misc
- local functions
- anonymous functions (lambdas)
- params
fn sum(params numbers)
Notes
- semicolons are optional
- parenthesis around keywords are optional. Both
if (condition)
andif condition
are valid - scopes are optional. Implicit scope is one statement.
a = 0 if 1 > 2 a = 2 print a
is valid - tabs are always discarded (no ident / dedent)
- newlines are almost always discarded
- dynamic type control. Optional static types. Implicit var declaration. Both
a = 0
andvar a = 0
is valid. In futureint a = 0
should be valid too. - SxScript is as permissive as possible. Aborting execution is always considered the last option. This is probably not a very good design but I love languages with this behavior (Lua).
- exceptions are not used to control flow (return, continue, break..)
Great projects I'd like to mention here
- https://github.com/codingseb/ExpressionEvaluator
- https://github.com/moonsharp-devs/moonsharp/
- https://github.com/scriban/scriban
- https://github.com/sebastienros/fluid
- https://github.com/sebastienros/jint
- https://github.com/microsoft/ClearScript
- https://github.com/munificent/craftinginterpreters (literature)