A simple, human-friendly, embeddable scripting language

Related tags

Command-line mica
Overview

Mica

Language reference · Rust API

Crate version

A simple, human-friendly scripting language, developed one feature at a time.

  • Human-friendly syntax inspired by Ruby and Lua
  • Simple yet extensible by providing a small amount of flexible language features
  • Easily embeddable into existing programs
  • Still highly work in progress!

You can try out the REPL with cargo run -p mica-cli --release.

Try it out

To compile Mica, use the following command:

$ cargo build -p mica-cli --release
# or, if you want to run it immediately:
$ cargo run -p mica-cli --release

Check out the language reference to have a detailed look at the language!

Performance

func factorial(n)
   i = 1
   x = 1
   while i <= n do
      x = x * i
      i = i + 1
   end
   x
end

iteration = 1
result = 0
while iteration <= 100000 do
   result = factorial(15)
   iteration = iteration + 1
end

print(result)

Factorial benchmark

> hyperfine --warmup 5 'target/release/mica code/functions.mi' 'lua5.1 code/functions.lua' 'python3 code/functions.py'
Benchmark 1: target/release/mica code/functions.mi
  Time (mean ± σ):      94.8 ms ±   6.8 ms    [User: 93.8 ms, System: 1.2 ms]
  Range (min … max):    91.5 ms … 121.1 ms    31 runs

Benchmark 2: lua5.1 code/functions.lua
  Time (mean ± σ):      27.5 ms ±   1.9 ms    [User: 26.7 ms, System: 1.2 ms]
  Range (min … max):    26.9 ms …  45.9 ms    97 runs

Benchmark 3: python3 code/functions.py
  Time (mean ± σ):     117.5 ms ±   1.3 ms    [User: 116.2 ms, System: 1.4 ms]
  Range (min … max):   115.6 ms … 119.9 ms    25 runs

Summary
  'lua5.1 code/functions.lua' ran
    3.44 ± 0.34 times faster than 'target/release/mica code/functions.mi'
    4.27 ± 0.30 times faster than 'python3 code/functions.py'

It's not ideal yet but hopefully it'll get better with time. Current bottlenecks include:

  • Stack-based rather than register-based virtual machine
  • Rust not having a way of doing direct threading in the interpreter dispatch loop. Tail calls when
  • The bytecode compiler not optimizing much

Why?

The Rust ecosystem has plenty of existing scripting languages, but none of them quite cuts it for me.

  • Lua is awesome, but I found mlua and rlua quite annoying to use due to their inability to bind most functions out of the box. You have to create wrapper functions that take giant tuples as arguments, which confuses the heck out of rustfmt, and is just plain inconvenient.
  • Rhai is nice, but the AST-walk interpreter is very slow. A waste of computer resources which I cannot afford to have in my programs.
  • Dyon… exists, but it seems more like an experimenting ground for implementing language features rather than a language designed for end users.
  • Rune is by far the most promising, but even the author admits that performance isn't the primary goal right now.
  • And there's plenty more languages, though these seem like the most prominent ones as far as I could tell. I also ruled out weird and wacky (including FP) languages, because due to current processor architectures they're doomed to remain merely research projects. Also, imperative languages are the most widely taught ones by far.

There's also a number of unfinished crates with bindings for more niche scripting languages that are written in C, but, well, they're unfinished.

I wanted a language that would take performance seriously. Be designed with specific goals in mind. Sugary, but not quite sweet enough to give you instant diabetes. And made by me.

Designing and implementing a programming language has been one of my arch nemeses for the past few years with varying levels of success, but I feel like finally, this is it. This time I'm gonna do it.

Comments
  • Garbage collection

    Garbage collection

    Some things simply cannot be collected when using reference counting, and even though GC is less predictable, that's not really something you worry about in high-level languages such as Mica.

    performance VM 
    opened by liquidev 4
  • Test runner

    Test runner

    The current test runner relies on a built version of mica to run its tests and on a bash-like shell. This is suboptimal since rust already provides a good framework, which also allows for parallel testing.

    To make use of this, I added a custom rust test runner, making use of libtest-mimic to emulate the base behavior of cargo test.

    This test runner loads all mica files from the tests folder and then runs them as actual tests with output, etc. It also identifies each test by using it's containing folder.

    To enable skipping of long tests (like with stress-1 or 2) it is possible to add a .skip extension to stop them from running by default and only run them when using cargo test -- --ignored.

    It is also possible to add basic exception testing. The example is failing.ml, in which we assert a false value and then check that the output contains the text "assertion failed". This is currently still pretty limited, but it would definitively be possible to expand this (i.e. by using .err files or sth. to compare more complex error outputs)

    opened by IcyTv 2
  • Constraints

    Constraints

    One thing that always annoys me in Lua is that when errors due to type mismatches occur, they usually appear really deep in the call stack unless you prepared yourself with all the appropriate assert(type(x) == "number", "argument x must be a number") which is very verbose and repetitive to write.

    As such I think Mica should have an option to add type annotations to function arguments.

    Syntax

    func name(x: T)
    

    The func syntax is augmented to accept an expression after a colon : for all parameters, specifying the constraint for the parameter. This syntax is optional for each parameter and propagates across parameters. For instance:

    func sin(x: Number)
      x.sin
    end
    

    The constraint is any value that implements the Constraint trait, defined as:

    trait Constraint
      func check(x)
    end
    

    The argument check receives is the argument received by the function, and the returned value's truth defines whether the constraint is satisfied or not. The returned value can also be a (false, String) tuple. In this case the returned string is used as the error message, formatted like type mismatch at argument N: <message>. Otherwise, the error message is type mismatch at argument N: expected T, but U does not satisfy the constraint, where N is the argument index (starting at 1), T is the constraint's name (Debug) and U is the name of the received value's type.

    All types (but not their values) implement Constraint by default, which simply checks if a value satisfies the given type.

    Implementing Constraint on custom types

    It should be possible to override Constraint for custom types, to implement range checks and the like. For example, a user-defined Range type could implement Constraint to check for values within a specified range.

    struct Range
    
    impl Range
      func new(min, max)
        @min = min
        @max = max
      end
    
      as Constraint
        func check(x)
          if !(x >= @min and x <= @max) do
            # Assuming the ~ operator is used for concatenation in the future
            (false, "value outside of of range(" ~ @min ~ ", " ~ @max ~ ")"))
          else
            true
          end
        end
      end
    end
    
    # A shorthand:
    func range(min, max)
      Range.new(min, max)
    end
    

    In practice, this would be used like so:

    func do_stuff(x: range(1, 10))
      print(x * 1000)
    end
    
    do_stuff(1)
    do_stuff(11)  # error
    
    enhancement language feature 
    opened by liquidev 2
  • GC sometimes SEGVs while collecting dtables

    GC sometimes SEGVs while collecting dtables

    This only happens in the REPL, and only sometimes.

    > "a"
    > "a"
    > Gc.collect
    

    Here's some fish code that reproduces the issue reliably:

    #!/usr/bin/fish
    
    while true
      printf \"a\"\n\"a\"\nGc.collect\n | ./target/debug/mica
      if test $status -ne 0
        exit 1
      end
    end
    
    bug GC 
    opened by liquidev 2
  • List and Dict types

    List and Dict types

    Currently Mica has no way of storing sequential or associative data. For that, we're going to need List and Dict types.

    A List is an ordered sequence of elements (in Rust speak, a Vec.) This name was chosen because it's more beginner-friendly; after all, why "vector"? As far as I can tell it just lists things.

    A Dict is basically just a Rust HashMap but with dynamic typing. This name was chosen because what the heck does "hash" mean, and as far as a beginner is concerned a map looks like this: A map of Europe (Image courtesy of Google Maps)

    Dict is short for dictionary which has one common meaning.

    Constructing lists

    Lists are constructed using square brackets [], which become a prefix token. Elements are comma-separated expressions.

    my_list = [1, 2, 3]
    
    list_literal := '[' (expression (',' expression)* ','?)? ']'
    prefix := list_literal
    

    Constructing dicts

    Dicts are also constructed using square brackets, however they use a: b pairs rather than single elements.

    my_dict = [
      "pi": Number.pi,
      "e": Number.e,
      "two": 2,
    ]
    
    dict_pair := expression ':' expression
    dict_literal := '[' (dict_pair (',' dict_pair)* ','?)? ']'
    prefix := dict_literal
    

    I chose to use [] instead of {} because everything can still be parsed predictively, and curly braces can remain reserved for tuples (#22).

    As far as new syntax goes, that's it.

    Accessing elements in the new data types

    Elements in lists and dicts can be retrieved using the get/1 method. There is no indexing operator, because I want to implement traits first (#38) before adding any new operators into the syntax. Likewise there is no joining operator.

    Other methods available on the two types should follow what Rust offers with Vec<T> and HashMap<K, V>.

    enhancement mod: corelib language feature 
    opened by liquidev 2
  • Update function syntax

    Update function syntax

    It would be nice if we had a way of implementing default functions in traits. However, with the current syntax we run into ambiguities:

    trait Name
      func my_required_function()  # How do we tell if this is a prototype or a default implementation?
    
      func my_default_function()
        10
      end
    end
    

    To alleviate this, a delimiter needs to be introduced after function declarations. The natural option is requiring a do..end block:

    func example(x) do
      print(x + 1)
    end
    

    I don't think it looks half bad in item context, but it's a little worse in anonymous functions:

    do_stuff(func (x) do x + 1 end)
    

    So an extra version for single expressions should be introduced, making use of = after the argument list.

    func add_one(x) = x + 1
    do_stuff(func (x) = x + 1)
    

    This version does not require an end. Of course, this leads to two stylistic choices that codebases can adopt:

    func add_one(x) do
      x + 1
    end
    # or
    func add_one(x) = do
      x + 1
    end
    

    But I think it's better to leave this to individual preference rather than make it a hard error.

    syntax 
    opened by liquidev 1
  • Make `struct Name` into an expression

    Make `struct Name` into an expression

    Declaring structs ahead of time is a necessity for supporting mutually recursive types, but most types aren't mutually recursive. Therefore it would make sense for struct Name to return the created type in addition to binding it to a variable Name.

    Combined with Mica's flexible impl blocks, this would allow for the following idiom:

    impl struct Vector
      func new(x, y) construct
        # ...
      end
    end
    
    language feature sugar 
    opened by liquidev 1
  • More string literals

    More string literals

    Currently the only string literal available is "abc", which is inconvenient for a few use cases:

    • No way to disable escape sequences
    • No way of writing ASCII characters, akin to Rust's b'a'
    • Hard to store code in literal strings

    Therefore I propose the following new literals:

    • Double-backslash like Zig:
      code =
      \\Hello, world!
      \\This is a multiline string literal.
      assert(code == "Hello, world!
      This is a multiline string literal.")
      
      • This gives the developer nice control over the indentation level of content inside the literal.
    • ~~ASCII character literals: assert(\a'a' == 97)~~ not needed if we have code points ↓
    • Unicode code points: assert(\u'ć' == \x107) - also needs a complementary String.nth_code_point method
    • Raw string literals: \r"C:\Windows\calc.exe"
      • We use a backslash before the r because I'd rather not have the lexer have to branch on identifiers or do other funny stuff.
    language feature sugar 
    opened by liquidev 1
  • Traits

    Traits

    After debating the whole idea with myself I have decided that standard library-level traits have too many drawbacks, and we need a proper language-level solution.

    Defining a trait

    A trait is defined using the trait keyword, followed by the name, followed by a list of function heads, terminated with end. A function head is the function's name, parameters, and calling convention, without the implementation. Only the instance calling convention should be supported for now; static functions can be added in later (probably after the GC and type are implemented). For instance, the standard library will define an Iterator trait for for loops:

    trait Iterator
      func has_next()
      func next()
    end
    
    trait := 'trait' identifier function_head* 'end'
    

    Implementing a trait

    A trait can be implemented by any arbitrary type, by using the as keyword inside of an impl block. For instance, to implement Iterator on a user-defined Repeat struct:

    struct Repeat
    
    impl Repeat
      func times(n) constructor
        @n = n
      end
    
      as Iterator
        func has_next()
          @n >= 0
        end
    
        func next()
          i = @n
          @n = @n - 1
          i
        end
      end
    end
    
    impl := 'impl' expression impl_item* 'end'
    impl_item := func_item | as_item
    as_item := 'as' expression func_item* 'end'
    

    Calling into trait methods

    For calling methods defined on traits, we can reuse the existing method call syntax. Combined with creating a struct full of static shims that call the actual method to represent the trait, we can use the syntax Iterator.has_next(repeat) to call the method has_next on repeat's implementation of Iterator.

    I considered a few other options:

    • repeat.Iterator.next - can be ambiguous if there are multiple traits with the same name implemented by a type
    • repeat.(Iterator).next, repeat.as(Iterator).next, (repeat as Iterator).next - all function the same way; they do a lookup of what next should mangle to given the trait Iterator in order to call the appropriate method on repeat, but that's unnecessary runtime work that can be done during compilation. In order to understand why the extra work is needed, we need to delve deeper into the implementation details…

    The implementation

    Traits should reuse the existing dtable mechanism, mainly because it's very fast (finding out a method's implementation is just an array lookup). The way this should be implemented is that function signatures get one more bit of mangling information - the ID of the trait a method is attached to (assuming that on creation a trait receives a unique ID).

    The reason why the three options I presented will be hard to implement, is that we need to find out the ID of the trait at runtime. But the trait ID is known during compilation, and as such each shim method in the trait knows the ID too, so the method ID can be precomputed at compile time.

    enhancement language feature 
    opened by liquidev 1
  • Calling Mica from Rust

    Calling Mica from Rust

    Right now it's possible to call Rust functions from Mica, so it should be possible to go the other way round - calling Mica functions from Rust. Right now the only way is to execute a chunk that calls the function with the desired parameters.

    Rust API 
    opened by liquidev 1
  • Optimized assignments

    Optimized assignments

    Right now assigning always returns a value, regardless of whether the value is actually used. This causes a lot of unneeded value cloning, which can be reduced by introducing separate opcodes for handling "sinking" assignments (those that do not clone the value but rather move, or sink it into the variable). The compiler has all the context it needs to know whether the result of an assignment is discarded or not.

    performance 
    opened by liquidev 1
  • Introduce `let` to separate declaration from assignment

    Introduce `let` to separate declaration from assignment

    Currently there's no way of telling whether you're creating a variable, or assigning to an existing one just by glancing at the declaration. This leads to more terse code, but it also creates code that is harder to reason about.

    While I do quite like the current syntax:

    { some, library, function } = require("test.library")
    
    i = 1
    while i < 10 do
        i = i + 1
    end
    

    I believe let would make the code much easier to reason about in large scripts:

    let { some, library, function } = require("test.library")
    
    let i = 1
    while i < 10 do
        i = i + 1
    end
    

    On an even more practical note, let also solves a syntax ambiguity that might throw people off with destructuring:

    a = 1
    do
        (a, _) = (2, nil)  # is `a` assigned to, or is a new `a` created?
    end
    

    Since pattern destructuring is going to be exclusive to let (for now), the above will no longer be ambiguous:

    let a = 1
    do
        let (a, _) = (2, nil)
    end
    
    language feature 
    opened by liquidev 0
  • New architecture

    New architecture

    aka. decoupling stuff into smaller parts.

    The plan is to split the monolithic Engine into many smaller components:

    • There'll be a new Engine that only contains an Environment. It will be used for compiling Scripts.
      • Scripts will no longer hold a mutable reference to the engine, and instead will use a unique ID assigned to the engine at its creation to ensure correctness.
    • Engines will also be used for creating Isolates, which will be the actual execution environments.
      • An Isolate is like a reusable replacement for a Fiber, except as the name suggests - it's completely isolated from other isolates. Each isolate has its own GC and global storage.
        • Scripts will no longer be able to write global variables, only read from them. Global variable shadowing will also not be allowed.
          • I'm also considering making global variables be part of the Engine, because hey they're immutable anyways. But we'll see how that goes.
    • In addition there will also be a Registry type - a dynamically typed storage container, basically a HashMap<TypeId, RefCell<Box<dyn Any>>>.
      • There will be two registries: the static registry (part of the Engine,) and the isolate registry (one per Isolate). Foreign functions will have a way of accessing these registries and mutating what's inside them.
      • This mechanism will be modeled to fit the requirements for implementing require.
    refactoring mod: hl 
    opened by liquidev 0
  • `implements` function

    `implements` function

    This function would simply return whether a type implements the provided trait.

    trait Example end
    
    struct MyType impl
      func new() constructor = nil
      as Example end
    end
    
    value = MyType.new
    assert(implements(value, Example))
    
    mod: corelib 
    opened by liquidev 1
  • Ready for use ?

    Ready for use ?

    Hi,

    I am working on a classical RPG Creator in Rust at https://github.com/markusmoenig/Eldiron. I am currently using Rhai for scripting but it's slow, I cannot use Lua etc. because it does not compile to WASM (I mean you can compile it to WASM but you cannot communicate with it).

    I like Mica, do you think it is ready for production ? I am half-way through my project so if I would want to switch it is now :)

    Cheers

    opened by markusmoenig 6
Releases(0.7.0)
  • 0.7.0(Oct 31, 2022)

    This release once again does not improve on anything within the language itself, but rather aims to improve the capabilities of the Rust API.

    • Breaking: Method parameters are now handled differently than function parameters.
      • There's a new type MethodParameterCount that's used for performing various math on parameter counts, safely.
        • This type limits parameter counts to fit in a u8, to reflect what the VM supports.
      • If you've only ever used the high-level ForeignFunction API, this does not affect you.
    • Breaking: Errors in mica::ll are now prefixed with Language - mica::ll::error::{ErrorKind, Error} are now mica::ll::error::{LanguageErrorKind, LanguageError}. This reflects what the API looked like pre-0.6.0.
    • Breaking: mica::ll foreign function ABI has changed, and how includes an &Environment parameter. [docs]
    • Breaking: Values do not implement From<T> anymore; these implementations were replaced with a new trait IntoValue, together with the new functions Value::new and Engine::create_value. The latter can be used to create user data values.

    And now for the exciting stuff!

    • It is now possible to accept Cloneable UserData as parameters in functions.
      • In a future release, this will be extended to references - this is not that release though.
    • It is also possible to return any UserData from functions.
      • Breaking: As a result of this change, TypeBuilder::add_constructor has been removed. The replacement is TypeBuilder::add_static, from which you can return any type implementing UserData.

    And probably a bunch of stuff I forgot about.

    Source code(tar.gz)
    Source code(zip)
  • 0.6.0(Oct 27, 2022)

    This release does not add any new features to the language or the API, but rather aims to refine the existing implementation a bit.

    • Breaking: mica-language, mica-hl, and mica-std are now consolidated into the singular mica crate.
      • mica-language is available under mica::ll, with ll standing for low-level.
      • mica-hl is reexported at the root of the crate.
      • The standard library mica-std has been renamed to the core library and is available under mica::corelib.
        • Following the rename, mica::StandardLibrary was renamed to mica::CoreLibrary.
        • The std-io feature was removed because it was largely unimplemented.
    • Breaking: Engine initialization has been simplified to just Engine::new(). This loads the default core library mica::corelib::Lib.
    • Thanks to the changes above, the documentation now features lots of examples, because you don't need mica-std to initialize an engine anymore!
    • Breaking: It is now impossible to create varargs methods inside of custom types. This was intended to be a feature initially but never got implemented; it can be implemented in a backwards-compatible way so restricting methods to fixed argument counts is only breaking one-way.
      • As part of this change, the TypeBuilder::add_raw_* family of functions now accepts a u16 parameter count rather than impl Into<Option<u16>>. This is still not ideal because methods can only ever accept up to 255 arguments, but it will do for the time being.
      • Also as part of this change, mica::ffvariants::Bare was split into BareMaybeVarargs and BareExactArgs to let us specify non-varargs functions explicitly.
    • Internal change: the giant macro in mica::hl for generating ForeignFunction implementations was removed in favor of offline code generation.
      • For users, this does not introduce a build.rs that would further extend compilation times - the generated code is checked into the repository.
      • In fact, our current build.rs was deemed unnecessary and has been removed. It only ever checked for NaN boxing support, which can be done just as well using existing #[cfg] directives.
    • Style change: Code is now indented with 4 spaces instead of 3. Yes, this includes Mica code.
      • The rustfmt.toml is definitely not final and may change in the future, perhaps to remove the unstable feature requirement, or wrap certain things (like struct initialization) more aggressively.
    Source code(tar.gz)
    Source code(zip)
  • 0.5.0(Sep 26, 2022)

    • #83 Updated function syntax [docs]
      • To resolve ambiguities with allowing to leave the body of a function empty, functions now use a new, shorter syntax.
      • Instead of func name() end, with the block being implicit, functions are now written like func name() = nil, where nil is the return value of the function. This value can be any expression.
      • Function expressions follow, and also use this new syntax. func () end becomes func () = nil.
      • Refer to the language documentation for more details.
    • #89 Postfix impl [docs]
      • The impl operator, which used to be spelled like impl expr end, is now spelled postfix: expr impl end.
      • This leads to struct definitions reading much more nicely, with the scoping of the newly declared struct being more obvious.
      • Example: impl struct Example end becomes struct Example impl end
    • #38 Traits [docs]
      • Mica now has support for traits (aka interfaces, protocols in other languages.)
      • Refer to the language documentation for details.
    • #36 for loops [docs]
      • Because we now have traits that allow for defining an iterator protocol that won't clash with user methods, for loops were introduced as a syntax sugar for iterating values produced by an object with while.
      • Note that Mica is still in alpha and the iterator protocol may be altered, should the need arise. For instance currently it's impossible to specify an implicit iterator for an object a'la Rust's FromIterator.
      • Currently the standard library has two iterators: CountUp and CountDown, which do exactly what they say on the tin. Iterators over things like dict pairs are not available yet because of limitations in mica-hl.
        • There's also the question of whether we want to reimplement the string iterators from the Rust standard library, which may introduce soundness bugs, but we'll see.
    Source code(tar.gz)
    Source code(zip)
  • 0.4.0(Jun 10, 2022)

    This release introduces a bunch of new literals, and adds some basic data structures.

    • #47 Improved number literals [docs]
      • Added \b, \o, \x, \radix:, and \u'C' literals for numbers.
      • Added the ability to use _ as a digit separator.
      • Added exponential notation.
    • #8 #46 Improved string literals [docs]
      • Added \r raw string literals, and \\ long string literals.
      • Added a bunch of common escape sequences for characters in strings.
      • Strings cannot contain embedded line breaks anymore. Use the \n escape sequence or a long string literal \\.
    • #54 struct Name is now an expression [docs]
      • This allows for a more concise way of creating and implementing a struct:
        impl struct Example
          # ...
        end
        
    • #60 List and Dict types [list docs] [dict docs]
      • Lists are a basic data structure for storing values sequentially. In Rust, they're known as Vec<T>.
      • Dicts are another basic data structure for storing unordered key-value pairs. In Rust, they're known as HashMap<K, V>.

    Refer to the language documentation for details and usage examples.

    Source code(tar.gz)
    Source code(zip)
  • 0.3.0(Apr 3, 2022)

    This release optimizes the Mica interpreter a ton, and adds the ability to call Mica functions and methods from Rust.

    • #20 Sinking assignments
      • Assignments that don't result in a value now generate more efficient bytecode than previously.
      • Basically, there's now a bunch of instructions for directly popping a value off the stack into a variable without making a copy.
    • #21 NaN boxing
      • Values inside the VM now take up 8 bytes instead of 24 bytes, which should improve cache efficiency.
    • #24 Garbage collection
      • This is the big star of the show, and improves performance drastically by reducing branch mispredictions caused by Dropping and Cloneing values.
      • Thanks to the GC values are now trivially dropped and copied.
      • mica-hl has received an overhaul of the value API because of this and NaN boxing, because the implementation of values is now hidden and our own Gc<T> instead of Rust's Rc<T> is used.
      • There's now a Gc type in Mica's standard library, for controlling the GC's operation.
    • #37 Calling Mica from Rust
      • Engine now exposes a bunch of functions that let you call any value the () call operator can be used on (right now only functions), as well as methods.
    • Various smaller fixes and optimizations. In particular, a huge performance regression introduced in 0.2.0 as a result of my desperate attempts to implement reentrancy, has now been fixed.
    Source code(tar.gz)
    Source code(zip)
  • 0.2.0(Mar 28, 2022)

Owner
Mica programming language
Mica is a human-friendly embeddable scripting language for Rust.
Mica programming language
This is choose, a human-friendly and fast alternative to cut and (sometimes) awk

Choose This is choose, a human-friendly and fast alternative to cut and (sometimes) awk Features terse field selection syntax similar to Python's list

Ryan Geary 1.4k Jan 7, 2023
Grep with human-friendly search output

hgrep: Human-friendly GREP hgrep is a grep tool to search files with given pattern and print the matched code snippets with human-friendly syntax high

Linda_pp 345 Jan 4, 2023
Simple low-level web server to serve file uploads with some shell scripting-friendly features

http_file_uploader Simple low-level web server to serve file uploads with some shell scripting-friendly features. A bridge between Web's multipart/for

Vitaly Shukela 2 Oct 27, 2022
Experimental extension that brings OpenAI API to your PostgreSQL to run queries in human language.

Postgres <> ChatGPT Experimental PostgreSQL extension that enables the use of OpenAI GPT API inside PostgreSQL, allowing for queries to be written usi

CloudQuery 315 Apr 10, 2023
An embeddable dynamic programming language for Rust.

rune Visit the site ?? - Read the book ?? An embeddable dynamic programming language for Rust. Contributing If you want to help out, there should be a

The Rune Programming Language 1.1k Dec 27, 2022
Codemod - Codemod is a tool/library to assist you with large-scale codebase refactors that can be partially automated but still require human oversight and occasional intervention

Codemod - Codemod is a tool/library to assist you with large-scale codebase refactors that can be partially automated but still require human oversight and occasional intervention. Codemod was developed at Facebook and released as open source.

Meta Archive 4k Dec 29, 2022
Fuzzy Index for Python, written in Rust. Works like error-tolerant dict, keyed by a human input.

FuzzDex FuzzDex is a fast Python library, written in Rust. It implements an in-memory fuzzy index that works like an error-tolerant dictionary keyed b

Tomasz bla Fortuna 8 Dec 15, 2022
Human numeric sorting program — does what `sort -h` is supposed to do!

hns — Human Numeric Sort v0.1.0 (⏫︎2022-09-20) © 2022 Fredrick R. Brennan and hns Authors Apache 2.0 licensed, see LICENSE. man page Packages hns_0.1.

Fredrick Brennan 7 Sep 25, 2022
Display file sizes in human-readable units

hsize Display file sizes in human-readable units $ hsize 1000 1000000 5000000 1.00 KB 1.00 MB 5.00 MB $ hsize -p 5 1048576 12345678 1.04858 MB 12.345

Ryan 2 Nov 21, 2022
The GameLisp scripting language

GameLisp GameLisp is a scripting language for Rust game development. To get started, take a look at the homepage. Please note that GameLisp currently

Fleabit 348 Nov 29, 2022
Open-source compiler for the Papyrus scripting language of Bethesda games.

Open Papyrus Compiler This project is still WORK IN PROGRESS. If you have any feature requests, head over to the Issues tab and describe your needs. Y

erri120 22 Dec 5, 2022
A plugin system for the Rhai embedded scripting language.

Rhai Dylib This crate exposes a simple API to load dylib Rust crates in a Rhai engine using Rhai modules. ?? This is a work in progress, the API is su

Rhai - Embedded scripting language and engine for Rust 6 Dec 27, 2022
Provides filesystem access for the Rhai scripting language.

About rhai-fs This crate provides filesystem access for the Rhai scripting language. Usage Cargo.toml [dependencies] rhai-fs = "0.1.2" Rhai script //

Rhai - Embedded scripting language and engine for Rust 6 Dec 5, 2022
YAL is Yet Another scripting Language(but worse)

YAL - Yet Another Language YAL is yet another scripting language(but worse). Syntax Basic syntax fun main() { print("Hello, World!"); } Fibonacci

MD Gaziur Rahman Noor 16 Nov 14, 2022
bevy_scriptum is a a plugin for Bevy that allows you to write some of your game logic in a scripting language

bevy_scriptum is a a plugin for Bevy that allows you to write some of your game logic in a scripting language. Currently, only Rhai is supported, but more languages may be added in the future.

Jarosław Konik 7 Jun 24, 2023
Synthia is a lightweight and beginner-friendly interpreted programming language developed in Rust

Synthia is a lightweight and beginner-friendly interpreted programming language developed in Rust. With a simple, intuitive syntax and a focus on ease of use, Synthia is perfect for both newcomers to programming and experienced developers looking for a flexible scripting language

Shiva 3 Oct 5, 2023
fd is a program to find entries in your filesystem. It is a simple, fast and user-friendly alternative to find

fd is a program to find entries in your filesystem. It is a simple, fast and user-friendly alternative to find. While it does not aim to support all of find's powerful functionality, it provides sensible (opinionated) defaults for a majority of use cases.

David Peter 25.9k Jan 9, 2023
Shell scripting that will knock your socks off

atom Shell scripting that will knock your socks off. NOTE: Click the image above for a video demonstration.

adam mcdaniel 256 Dec 14, 2022
A command line interface meant to bridge the gap between Rust and shell scripting

clawbang A command line interface meant to bridge the gap between Rust and shell scripting. Intended for use with HEREDOCs and shebangs: $ clawbang <<

Chris Dickinson 52 Mar 25, 2022