Lisp dialect scripting and extension language for Rust programs

Overview

Ketos

Ketos is a Lisp dialect functional programming language.

The primary goal of Ketos is to serve as a scripting and extension language for programs written in the Rust programming language.

Ketos is compiled to bytecode and interpreted by pure Rust code.

API Documentation

ketos_derive Documentation

Language Documentation

Building the library

To build Ketos into your Rust project, add the following to your Cargo.toml:

[dependencies]
ketos = "0.11"

And add the following to your crate root:

extern crate ketos;

Building the REPL

Build and run tests:

cargo test

Build optimized executable:

cargo build --release

Usage

ketos can be run as an interpreter to execute Ketos code files (.ket) or run as an interactive read-eval-print loop.

License

Ketos is distributed under the terms of both the MIT license and the Apache License (Version 2.0).

See LICENSE-APACHE and LICENSE-MIT for details.

Comments
  • About sexp by sexp multi line editing

    About sexp by sexp multi line editing

    I saw ketos' repl handles sexp across multi lines in the following way ::

    ketos=> (+ 1 2
    ketos(> 3
    ketos(> (+ 4 5
    ketos(> )
    ketos(> )
    15
    ketos=>
    

    Is it possible to use linefeed to support sexp by sexp multi line editing ? (like the repl of chez-scheme)

    (see also https://github.com/kkawakam/rustyline/issues/153)

    opened by xieyuheng 9
  • Add Bitwise operators

    Add Bitwise operators

    I was very pleased to find this project, it was almost exactly what I was looking for. One thing I was missing was bitwise operators, so I implemented them. If this isn't what you want for ketos, go ahead and close the PR.

    My main concern is in the naming of the ketos functions: I see there is a tendency to use terse function names. so I made AND & and OR |. For XOR, I went with bit-xor since ^ is already being used for exponentiation. I considered naming the others bit-and and bit-or, but it didn't seem to be consistent with the shift functions.

    Since it's pre 1.0 software, I would assume there's some flexibility. I imagined you could:

    • rename ^ to pow (Maybe even stick it in the math module) and use &, | and ^ for bitwise.
    • all three could be named bit- while considering using something like shiftl and shiftr

    If you're interested, but would like some changes, please let me know! Thank you for building this project.

    opened by jcpst 6
  • Allow Global Scope clone

    Allow Global Scope clone

    It is possible to allow cloning of the global scope?

    I have a server that receives many requests, I want to be able to execute code from a base scope from each request, without values or macros defined in any given request leaking into the global scope.

    opened by samdesota 6
  • Trouble deriving attributes for structs with particular fields

    Trouble deriving attributes for structs with particular fields

    I'm having a problem when trying to define a structure that creates a data structure such as a tree or list:

    ...
    #[derive(Clone, Debug, ForeignValue, FromValueClone, StructValue)]
    pub struct LList {
        data: String,
        point: Option<Box<LList>>,
    }
    ...
    

    This causes the complier to throw errors related to point. I tried creating wrapper structures for Option and Box and deriving the attributes on those, but that failed.

    I hope I'm not missing something simple, I'm still a bit new to Rust.

    opened by Wulfsta 5
  • Cannot insert variable into global scope from within `let`.

    Cannot insert variable into global scope from within `let`.

    Attempting to use define to insert a variable into the global scope from within a let statement throws an error. A minimal example to demonstrate

    extern crate ketos;
    
    use ketos::{Interpreter, FromValue};
    
    fn main() {
        let interp = Interpreter::new();
    
        match interp.run_code(r#"
            (let ((plus +) (mult *)) (
                (define ten (mult (plus 3 2) 2))
            ))
            "#, None) {
            Ok(k) => k,
            Err(e) => panic!(interp.display_error(&e)),
        };
    
        let m = i32::from_value(interp.get_value("ten").unwrap()).unwrap();
    
        println!("{}", m);
    }
    

    will throw

    execution error: type error: expected function; found name: ten
    

    In contrast, if we change the Ketos code executed to

    ...
    match interp.run_code(r#"
        (define ten (* (+ 3 2) 2))
    "#, None) {
    ...
    

    this code executes without error, printing 10.

    opened by Wulfsta 4
  • Doc-strings for methods

    Doc-strings for methods

    It would be cool to allow defines to be written like that:

    (define (foo a b c)
      "Documentation string"
      (+ a b c))
    

    This would be great step into making Ketos fully usable language for real development (no need for documentation generator yet).

    opened by hauleth 4
  • Inconsistent arithmetic

    Inconsistent arithmetic

    ketos=> (+)
    0
    ketos=> (+ 1)
    1
    ketos=> (-)
    compile error: `-` expected at least 1 argument; found 0
    ketos=> (- 1)
    -1
    ketos=> (*)
    1
    ketos=> (* 1)
    1
    ketos=> (/)
    compile error: `/` expected at least 1 argument; found 0
    ketos=> (/ 1)
    1/1
    

    I would expect the following evaluations:

    ketos=> (-)
    0
    ketos=> (/)
    1
    ketos=> (/ 1)
    1
    
    opened by vks 4
  • [Suggestion] More module functionality

    [Suggestion] More module functionality

    Pretty much just

    (use module :self)
    (module/function "argument")
    

    Examples

    (use math :self)
    (print (math/abs -1))
    

    Result: 1


    ; foo.ket
    (export (bar baz))
    
    (define (bar a) (print (concat a "bar")))
    (define (baz b) (print (concat "baz" b)))
    
    ; main.ket
    (use foo :self)
    
    (foo/bar "foo")
    

    Result: foobar

    I understand that in the previous examples they could have instead been (use module function), (use math abs), and (use foo bar), but this syntax is convenient when you don't want conflicting function/struct names or you want to be more specific and organized with them.

    Basically, I think adding functionality like this would make Ketos a more powerful language.

    opened by wackbyte 3
  • 2018 edition

    2018 edition

    This just applies the automatic fixes from cargo fix --edition, and sets the edition in Cargo.toml. It does not take advantage of some of the new features in the 2018 edition (as mentioned in #44), since they aren't backwards compatible. Should they be included?

    opened by ysimonson 3
  • Keyword/enum conversion using IntoValue and FromValue

    Keyword/enum conversion using IntoValue and FromValue

    I've been thinking about treating keywords as enum values, e.g. enum Foo { Bar, Baz } <=> :Bar and :Baz, which would be nicely derive-able. However, a Keyword value requires a NameStore to find its string value, which means you can't IntoValue or FromValue it.

    I can think of a couple of ways around this:

    • Add a Scope argument to conversion functions, so they can do a lookup if necessary
    • Change keywords to Keyword(String) in the Value enum, or add Symbol(String), to make self-representing keywords or symbols, as with similar parenthesized languages
    • Make string<->keyword conversion functions (which might be useful anyway!) that can be added in automatically by interop macros.

    I'd be happy to dive in and make a PR, but each of these has trade-offs! Also, is there a better way I've not thought of?

    [EDIT] Or a new EnumValue trait similar to StructValue, but I'm not sure what kind of machinery would need to go in there.

    opened by vklquevs 3
  • Access to context inside rust bindings.

    Access to context inside rust bindings.

    So I have this function in rust bound to ketos that receives a lambda as an argument and calls the lambda in a loop with a different value for its arguments on every run.

    Sounds simple enough, but my function can't receive the context as a parameter, so I'm stuck using the interpreter as a global variable.

    I understand that functional languages are not supposed to care about the context, but all functions I've found to execute the lambda require me to send the context as a parameter.

    What should I do?

    opened by Rafagd 3
  • More use of feature flags to reduce compile time and binary size

    More use of feature flags to reduce compile time and binary size

    In order to facilitate smaller binaries, it would be useful to put some features behind feature flags. For example:

    • mod_random could be gated to remove a dependency
    • all REPL features/dependencies should be gated away and not included by default
      • installation for the REPL binary would need need to be cargo install --feature repl ketos which seems fine
    opened by brassy-endomorph 0
  • WebAssembly support

    WebAssembly support

    Adds conditional compilation for the wasm32 target to enable wasm support. Tested with a small program on Firefox 88.0.1 and it works well enough. It requires a nightly compiler to access std::time::Instant in a way that doesn't panic. Possibly as a result of using the nightly compiler, it errors on test execution with the following:

    $ cargo test --target wasm32-unknown-unknown --no-default-features
    ...
        Finished test [unoptimized + debuginfo] target(s) in 0.02s
         Running unittests (target/wasm32-unknown-unknown/debug/deps/ketos-951c6b0f1e1fa322.wasm)
    /home/user/code/misc/ketos/target/wasm32-unknown-unknown/debug/deps/ketos-951c6b0f1e1fa322.wasm: 1: /home/user/code/misc/ketos/target/wasm32-unknown-unknown/debug/deps/ketos-951c6b0f1e1fa322.wasm: Syntax error: end of file unexpected
    
    opened by brassy-endomorph 0
  • [feature request] function define in a function define

    [feature request] function define in a function define

    ketos=> (define (x)
                (define (x-1) "hello")
                (x-1))
    Traceback:
    
      In main, define x
    
    execution error: type error: expected string; found list: (define (x-1) "hello")
    

    Would something like this be planned to be added to ketos? #60 is related in the sense that let-rec, and define in this way would achieve lambda recursion as well.

    opened by Inc0n 1
  • Add basic time module

    Add basic time module

    This pull request would add a basic time module. The module provides two functions (utc-timestamp and local-timestamp) that return the current time in UTC or your local timezone as the number of seconds since January 1st 1970. The module uses chrono::offset to get the time in UTC and your local timezone and will add a dependency on chrono version 0.4.

    If anyone would like to write a more complete time library I can help. This module is currently an minimal implementation containing only what I need.

    opened by michardy 0
  • How can a lambda call itself?

    How can a lambda call itself?

    I'm trying to create a function that returns a function that calls itself. I tried this:

    (define (multo ex) (let ((f (lambda (n) (if
                            (= 0 n)
                            1
                            (* ex (f (- n 1))))))) f))
    (println "~s" ((multo 3) 3))
    

    But it doesn't work because the lambda can't refer to f inside the definition. How do I achieve this?

    opened by bouk 2
Owner
Murarth
Murarth
A rusty dynamically typed scripting language

dyon A rusty dynamically typed scripting language Tutorial Dyon-Interactive Dyon Snippets /r/dyon Dyon script files end with .dyon. To run Dyon script

PistonDevelopers 1.5k Dec 27, 2022
Scripting language focused on processing tabular data.

ogma Welcome to the ogma project! ogma is a scripting language focused on ergonomically and efficiently processing tabular data, with batteries includ

kdr-aus 146 Dec 26, 2022
A static, type inferred and embeddable language written in Rust.

gluon Gluon is a small, statically-typed, functional programming language designed for application embedding. Features Statically-typed - Static typin

null 2.7k Dec 29, 2022
Source code for the Mun language and runtime.

Mun Mun is a programming language empowering creation through iteration. Features Ahead of time compilation - Mun is compiled ahead of time (AOT), as

The Mun Programming Language 1.5k Jan 9, 2023
Implementation of Immix Mark-Region Garbage collector written in Rust Programming Language.

libimmixcons Implementation of Immix Mark-Region Garbage collector written in Rust Programming Language. Status This is mostly usable library. You can

playX 34 Dec 7, 2022
A computer programming language interpreter written in Rust

Ella lang Welcome to Ella lang! Ella lang is a computer programming language implemented in Rust.

Luke Chu 64 May 27, 2022
Interpreted language developed in Rust

Xelis VM Xelis is an interpreted language developed in Rust. It supports constants, functions, while/for loops, arrays and structures. The syntax is s

null 8 Jun 21, 2022
REPL for the Rust programming language

Rusti A REPL for the Rust programming language. The rusti project is deprecated. It is not recommended for regular use. Dependencies On Unix systems,

Murarth 1.3k Dec 20, 2022
Oxide Programming Language

Oxide Programming Language Interpreted C-like language with a Rust influenced syntax. Latest release Example programs /// recursive function calls to

Arthur Kurbidaev 113 Nov 21, 2022
The hash programming language compiler

The Hash Programming language Run Using the command cargo run hash. This will compile, build and run the program in the current terminal/shell. Submit

Hash 13 Nov 3, 2022
Interactive interpreter for a statement-based proof-of-concept language.

nhotyp-lang Nhotyp is a conceptual language designed for ease of implementation during my tutoring in an introductive algorithmic course at Harbin Ins

Geoffrey Tang 5 Jun 26, 2022
🍖 ham, general purpose programming language

?? ham, a programming language made in rust status: alpha Goals Speed Security Comfort Example fn calc(value){ if value == 5 { return 0

Marc Espín 19 Nov 10, 2022
A small programming language created in an hour

Building a programming language in an hour This is the project I made while doing the Building a programming language in an hour video. You can run it

JT 40 Nov 24, 2022
The Loop programming language

Loop Language Documentation | Website A dynamic type-safe general purpose programming language Note: currently Loop is being re-written into Rust. Mea

LoopLanguage 20 Oct 21, 2022
Stackbased programming language

Rack is a stackbased programming language inspired by Forth, every operation push or pop on the stack. Because the language is stackbased and for a ve

Xavier Hamel 1 Oct 28, 2021
Diplo is a script runner and dependency manager made in rust mainly for Deno.

Diplo is a script runner and dependency manager made in rust mainly for Deno. Documentation Tricked.pro/diplo Installing - windows installer Features

Tricked 23 May 9, 2022
A Python compiler targeting JS, implemented in Rust.

A Python compiler targeting JavaScript, implemented in Rust.

Gideon Grinberg 5 Jun 17, 2021
A safe-against-invalid-input version of wren.io, written in Rust.

safe_wren A nearly-complete implementation of the Wren language (wren.io) in Rust. The original https://github.com/wren-lang/wren from wren.io is refe

Rubber Duck Engineering 20 Jul 16, 2022
Orion is a lisp dialect.

Orion Orion is a lisp inspired statically typed programming language written in Rust Install From releases Download binary from the releases. With car

Wafelack 226 Dec 17, 2022
Milho (corn in portuguese) is a toy dialect of Lisp written as a way to learn more about compilers

Milho (corn in portuguese) is a toy dialect of Lisp written as a way to learn more about compilers. There are implementations in rust and go

Celso Bonutti 27 May 4, 2022