Git Product home page Git Product logo

udem-dlteam / ribbit Goto Github PK

View Code? Open in Web Editor NEW
439.0 439.0 43.0 5.6 MB

A small and portable Scheme implementation with AOT and incremental compilers that fits in 4K. It supports closures, tail calls, first-class continuations and a REPL.

License: BSD 3-Clause "New" or "Revised" License

Makefile 1.24% C 10.35% Scheme 25.86% Python 4.57% JavaScript 1.12% HTML 0.33% Go 0.87% Shell 15.34% CMake 0.01% Haskell 5.16% Idris 7.28% Java 0.02% Ruby 0.02% Rust 1.39% Scala 7.25% Lua 4.14% OCaml 8.62% Assembly 3.23% Prolog 1.52% Clojure 1.69%

ribbit's People

Contributors

andrewkyle avatar ecoral360 avatar feeley avatar jamestjw avatar kolmogorov-fan-account avatar l4haie avatar laurenthuberdeau avatar leo-ard avatar mbernard2 avatar mguo763 avatar samuelyvon avatar seriousbusiness100 avatar shawnw avatar theadvancedone avatar zwizwa avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ribbit's Issues

Missing license

Hi there! Ribbit looks very interesting. It would be helpful if you could add a license to the code so that users and contributors know what the terms of use are. Thanks!

Using a chicken-compiled rsc crashes

$ csc -o rsc.chicken -O2 rsc.scm 
$ RSC_SCHEME_INTERPRETER=csi ./rsc -c ./rsc.chicken -t c -l max test.scm

Error: (cdr) bad argument type: ()

	Call history:

	rsc.scm:172: make-table	  
	rsc.scm:566: rib	  
	rsc.scm:1737: cmd-line	  
	rsc.scm:98: chicken.process-context#command-line-arguments	  
	rsc.scm:1737: parse-cmd-line	  	<--
*** compilation error:

Issues is that chicken's (command-line-arguments)doesn't include the name of the program, and rsc ends up trying to take the cdr of an empty list. PR with a fix coming shortly.

is it possible to got assembly code for the RVM code?

The print hello rvm code is );'u?>vD?>vRD?>vRA?>vRA?>vR:?>vR=!(:lkm!':lkv6y
and after decode , it's byte code array is
[3, 19, [3, 0, [3, 1, [0, [[0, [[...], [[[0, 0, 5], [[0, 0, 5], 0, 3], 2], [[[0, 0, 5], [[0, 0, 5], 0, 3], 2], [[[0, 0, 5], [[0, 0, 5], 0, 3], 2], [[0, [[0, 0, 5], 0, 3], 2], [[0, [[0, 0, 5], 0, 3], 2], [[0, [[0, 0, 5], 0, 3], 2], [0, 0, 5], 0], 0], 0], 0], 0], 0], 0], 1], [[0, 0, 5], 0, 3], 2], [1, [0, [[0, 0, 5], 0, 3], 2], [3, 2, [3, 0, [3, 1, [0, [[0, [[...], [[[0, 0, 5], [[0, 0, 5], 0, 3], 2], [[[0, 0, 5], [[0, 0, 5], 0, 3], 2], [[[0, 0, 5], [[0, 0, 5], 0, 3], 2], [[0, [[0, 0, 5], 0, 3], 2], [[0, [[0, 0, 5], 0, 3], 2], [[0, [[0, 0, 5], 0, 3], 2], [0, 0, 5], 0], 0], 0], 0], 0], 0], 0], 1], [[0, 0, 5], 0, 3], 2], [1, [0, [[0, 0, 5], 0, 3], 2], [3, 72, [0, [0, [[0, 0, 5], 0, 3], 2], [0, [0, [[0, 0, 5], 0, 3], 2], [3, 69, [0, [0, [[0, 0, 5], 0, 3], 2], [0, [0, [[0, 0, 5], 0, 3], 2], [3, 76, [0, [0, [[0, 0, 5], 0, 3], 2], [0, [0, [[0, 0, 5], 0, 3], 2], [3, 76, [0, [0, [[0, 0, 5], 0, 3], 2], [0, [0, [[0, 0, 5], 0, 3], 2], [3, 79, [0, [0, [[0, 0, 5], 0, 3], 2], [0, [0, [[0, 0, 5], 0, 3], 2], [3, 33, [0, [0, [[0, 0, 5], 0, 3], 2], [0, [0, [[0, 0, 5], 0, 3], 2], [3, 10, [0, [0, [[0, 0, 5], 0, 3], 2], 0]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]

I am wondering can we got assembly code for rvm code such like

const 19 
const 0
const 1
rib
...
call
pop
...

Trouble compiling REPL

I've been having a great time trying out Ribbit. Thank you for writing it and making it available. It's a real tour de force.

Alas, I've been having trouble getting the REPL to work. For example, here are my attempts to get it working through assembly language and C:

> echo "(repl)"|./rsc -t asm -l max-tc>/tmp/max-tc-repl.asm
> host/asm/asm2exe.sh /tmp/max-tc-repl.asm -o /tmp/max-tc-repl
> /tmp/max-tc-repl
> (define factorial (lambda (n) (if (< n 2) 1 (* n (factorial (- n 1))))))
0
> (factorial 10)
*** type error ()
> > echo "(repl)"|./rsc -t c -l max-tc>/tmp/max-tc-repl.c
> gcc /tmp/max-tc-repl.c
> ./a.out
> (define factorial (lambda (n) (if (< n 2) 1 (* n (factorial (- n 1))))))
0
> (factorial 10)
*** type error ()
> (define add1 (lambda (x) (+ x 1)))
0
> (add1 1)
*** type error ()
>

The prebuilt C version, when compiled, works fine with the same input.

I get the same results when I build the REPL this way:

> ./rsc -t asm -l max-tc repl-max.scm
> host/asm/asm2exe.sh repl-max.scm.asm -o /tmp/repl-max
> /tmp/repl-max
> (define add1 (lambda (x) (+ x 1)))
0
> (add1 1)
*** type error ()
>

Please forgive me if I'm missing something obvious.

lightweight, shareable datatypes

Question:
What do you think about simple and lightweight data types (simple string type and a list list type) that are sharable between Scheme and the host without the need for conversion?

Shared, bidirectionally usable data types:
string, float, array

Reasoning:

It is really great to see how ribbit can handle real Scheme code on all those different hosts with this simple runtime. With the new 'feature' system' it is possible to interweave Scheme and its recursive deeply nested and self-evaluating nature with all those different mostly down-to earth imperative hosts.

The price you pay for this integration are datatype conversion for all types. But in my day I do a lot of simple imperative-heavy scripting and in this world you deal with simple string types (maybe numbers) and lists (arrays), and frankly that is good enough for alot of tasks. There is very little nested data manipulation and recursion involved.

In this case Ribbit would demand alot of data conversion from the host system, which is not really necessary, or at least not worth the trouble.

So I think there some overhead and therefore it would be great to have at least one string-like sharable datatype.

Have a way to specify escaped characters in bytecode on a per-target basis

Instead of the current treat-all-targets-the-same approach.

Target A might need $'s escaped to \$, but doing that in Target B causes an error when you try to run it, for example. Or there are languages like SQL where backslash isn't the escape character.

Use a file in the hosts/N directories to controls escapes? Maybe an executable filter script that the stringified bytecode is run through before being inserted into the rvm file...

Various improper results from fresh compiled repl-min.scm

Have been exploring ribbit a bit lately, and working on a Zig implementation (which will probably diverge a lot from this as I explore additions to the RVM). Anyway, in the midst of trying to understand the RVM decoding, I encountered the following on a fresh git clone:

~/tmp/ribbit/src $ csi -q rsc.scm -t c -l min -m repl-min.scm 
~/tmp/ribbit/src $ gcc -o rvm.min repl-min.scm.c
~/tmp/ribbit/src $ ./rvm.min
> (string-length "hello")
()
> (string-ref "hello" 1)
Segmentation fault (core dumped)
apg@hc-apg:~/tmp/ribbit/src $ grep fer-gnirts repl-min.scm.c
    "Detouq,htgnel-gnirts,fer-gnirts,fi,!rdc-tes,tsil>-rotcev,!tes-gnirts,"
char *input = "E!rdc-tes,rddc,=,htgnel-gnirts,fer-gnirts,!tes-gnirts,gnirts-ekam,?rotcev,tsil>-
    ***SNIP***

As you can see, string-ref is in there, so the segfault is not occurring due to an unknown procedure or something (it would seem). Loading gdb:

~/tmp/ribbit/src $ gcc -g -o rvm.min.g repl-min.scm.c 
~/tmp/ribbit/src $ ./rvm.min.g 
> (string-ref "hello" 1)
Segmentation fault (core dumped)
~/tmp/ribbit/src $ gdb ./rvm.min.g 
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04.1) 9.2
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./rvm.min.g...
(gdb) run
Starting program: /home/apg/tmp/ribbit/src/rvm.min.g 
> (string-ref "hello" 1)

Program received signal SIGSEGV, Segmentation fault.
prim (no=6) at repl-min.scm.c:440
440         push2(CAR(x), PAIR_TAG);

I'd try this with min-tc, which I suspect might provide more clues, but that doesn't exist.

I did test the min defintions of list-ref and list-tail in chicken "just to be sure":

#;1> (define (list-ref lst i)
   (car (list-tail lst i)))

Note: assignment to imported value binding: list-ref
#;2> (define (list-tail lst i)
     (if (< 0 i) (list-tail (cdr lst) (- i 1)) lst))

Note: assignment to imported value binding: list-tail
#;3> (list-ref (string->list "hello") 1)
#\e

Finally, doing the same thing with the repl-max, I get correct results:

~/tmp/ribbit/src $ csi -q rsc.scm -t c -l max -m repl-max.scm 
~/tmp/ribbit/src $ ls
host  minify.scm    repl-max.scm.c  repl-min.scm.c  rvm.min
lib   repl-max.scm  repl-min.scm    rsc.scm         tests
~/tmp/ribbit/src $ gcc -o rvm.max repl-max.scm.c 
~/tmp/ribbit/src $ ./rvm.max
> (string-length "hello")
5
> (string-ref "hello" 1)
101
> 

In the min.scm, library string-length is an alias to field1 which makes this pretty interesting. I would say that field1 is somehow not linked properly, but it's of course a primitive. Also, car and cdr work just fine.

Also of note that using -l max and compiling repl-min works just fine. I guess it's possible that I should have no expectation that this works, but figured I'd raise it anyway.

Guidance for using on a RAM limited micro controller?

Thank you for making ribbit! This project is very cool.
I am particularly interested in using this for micro controllers.

The one I'm dealing with for my current project at work has a ARM Cortex M0+ processor and 48k RAM (about 38-40k available) and 144kb ROM.

I had seen this:

Ribbit achieves a 4K footprint, but that just means the size of the Ribbit VM plus the size of the compacted compiled code. The uncompacted code is stored in RAM in the form of linked "ribs" (3 cell objects, or 6/12/24 bytes depending on the word size) and this is not very memory efficient compared to a bytecode representation. So it takes on the order of 64K RAM to run the REPL, which is about 1000 lines of Scheme code. So a rule of thumb is about 64 bytes of RAM per line of Scheme code. You can use that ratio to determine how large of a Scheme program will fit on your specific device.

So if I understand correctly, my ideal of having a REPL on the MCU over UART is out of the question for this MCU. But perhaps, if the memory needed for the VM itself is small enough, you could have the encoded instructions compiled on the computer, sent over UART, and run on the MCU?

That way even if you could not have a true REPL, you would still only need to recompile and restart the instructions for the VM, and not recompile/upload/run the entire C program.

Missing makefiles?

A few host sub directories have makefiles that reference ../../makefile-common.mk, which doesn't exist in the repository. And the main readme mentions some make targets that can be run from the src directory, but there's no Makefile there either.

Decouple generated filenames from hosts

Currently, the name of the host is used both for the directory in the hosts tree to look for a rvm file, and the file extension to use. ./rsc -t N foo.scm looks for hosts/N/rvm.N and creates foo.scm.N.

It would be nice for there to be a way to map a name to a different extension - so you can have multiple targets using the same language but different implementations, and better handle cases where the extension is used by multiple languages (Like .ml being used by ocaml and standard ML).

Some languages might have trouble with source files like foo.scm.N instead of foo.N, too, so a generic way to transform filenames might be useful as well.

Exception handling

Exception handling (raise / guard) is mandatory for useful Scheme programming. What's the plan for supporting it? I assume it can be implemented using continuations; is that usable enough?

latest gsi -t py error

usr/local/Gambit/bin/gsi --version
*** WARNING -- Unknown or improperly placed --version option ignored (try -help)
Gambit v4.9.3-1616-ga5b8ee9f

/usr/local/Gambit/bin/gsi rsc.scm -t py  -l min repl-min.scm
*** ERROR IN loop4, "rsc.scm"@1266.33 -- Unbound variable: append-strings

Lua interpreter

Hi,
Nice project!
This is not an issue, just a question.
I started transliterating the Python VM to Lua but it dawned on me that the Python code might have been generated.
Is this the case, and if so, is the generator available?
Cheers,
Tom

How to add host functions?

Is there is a simple way to add a function from the host platform?

Something like ##inline-host-statement or ##inline-host-expression from Gambit Scheme.

`eval` and `compile` procedure not working for `min`/`max` library when `arity-check` is disabled

To reproduce (on dev branch):

> gsi -:r4rs rsc.scm -t js -l min -x test tests/00-ribbit/35-eval.scm -o test.js
> /test <<< "(* 6 7)"                                                          
/home/leonard/code/dirowars/ribbit/src/test:157
    let o = pc[1];
              ^

TypeError: Cannot read properties of undefined (reading '1')
    at run (/home/leonard/code/dirowars/ribbit/src/test:157:15)
    at Object.<anonymous> (/home/leonard/code/dirowars/ribbit/src/test:223:3)
    at Module._compile (node:internal/modules/cjs/loader:1254:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1308:10)
    at Module.load (node:internal/modules/cjs/loader:1117:32)
    at Module._load (node:internal/modules/cjs/loader:958:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:23:47

Node.js v18.16.0

This bug is reproducible in py, js and asm hosts.

However, if we activate arity-check, then everything runs fine :

> gsi -:r4rs rsc.scm -t js -l min -f+ arity-check -x test tests/00-ribbit/35-eval.scm -o test.js
> ./test <<< "(* 6 7)"                                                                          
42

This bug is probably due to changes in the calling protocol, and min/max libraries where not updated accordingly. The bug is probably in the min/max library.

Crash at repl (Node.js)

Using head.

$ guile -s rsc.scm -t js -l min repl-min.scm
$ node repl-min.scm.js
> 42
42
> (define x 42)
0
> x
42
> '(a b)
(a b)
> `(a b c (d e))
#f
> /home/hugo/Downloads/ribbit-main/src/repl-min.scm.js:177
    let o = pc[1];
              ^

TypeError: Cannot read property '1' of undefined
    at run (/home/hugo/Downloads/ribbit-main/src/repl-min.scm.js:177:15)
    at Object.<anonymous> (/home/hugo/Downloads/ribbit-main/src/repl-min.scm.js:235:13)
    at Module._compile (internal/modules/cjs/loader.js:1085:14)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
    at Module.load (internal/modules/cjs/loader.js:950:32)
    at Function.Module._load (internal/modules/cjs/loader.js:790:12)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:76:12)
    at internal/main/run_main_module.js:17:47

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.