Author Topic: TinyScheme  (Read 59730 times)

0 Members and 1 Guest are viewing this topic.

JRS

  • Guest
TinyScheme
« on: August 23, 2014, 03:49:50 PM »



Quote
TinyScheme is a lightweight Scheme interpreter that implements as large a subset of R5RS as was possible without getting very large and complicated. It is meant to be used as an embedded scripting interpreter for other programs. As such, it does not offer IDEs or extensive toolkits although it does sport a small top-level loop, included conditionally. A lot of functionality in TinyScheme is included conditionally, to allow developers freedom in balancing features and footprint.

As an embedded interpreter, it allows multiple interpreter states to coexist in the same program, without any interference between them. Programmatically, foreign functions in C can be added and values can be defined in the Scheme environment. Being a quite small program, it is easy to comprehend, get to grips with, and use. TinyScheme was grown out of the MiniScheme distribution during the development of Ovrimos.

Author / project home page

Current TinyScheme source - SourceForge - 1.41

Github Repository - Windows makefile for MinGW - 1.40

TinyScheme Documentation

Scheme R5RS Spec.

The Internet Scheme Repository
« Last Edit: September 03, 2014, 08:24:00 PM by John »

JRS

  • Guest
TinyScheme
« Reply #1 on: August 23, 2014, 05:29:41 PM »
While Mike is getting BASIC Lisp in shape and ready for testing, I thought I would experiment with TinyScheme as it's embeddable and seems to have many of the syntax features Rob has been after. Here is my first test of Tiny Scheme embedding with C.

Helpful Scheme Tutorial

Code: [Select]
//
// Tiny example of embedding TinyScheme in your code
// by Dmitry Chestnykh <dmitry@codingrobots.com>
// Public domain
//
//
// Compile
// --------
// $ cc example.c -L./ -ltinyscheme -o example
//
// Note: if you want to statically, link, first compile tinyscheme as NOT standalone.
// To do this, change scheme.h: # define STANDALONE 0   (instead of 1)
// Then 'make'. Forget about errors. Remove libtinyscheme.so (leave only static library .a)
// And then compile this example as written above.
//
//
// Run
// ---
// $ ./example
//
// Output
// --------------
// Hello, world!
// Answer: 42

#include <stdio.h>

#define USE_INTERFACE 1

#include "scheme.h"
#include "scheme-private.h"

// display -- scheme function
// Example: (display "Hello")
// This version only displays strings
pointer display(scheme *sc, pointer args) {
  if (args!=sc->NIL) {
    if (sc->vptr->is_string(sc->vptr->pair_car(args)))  {
      char *str = sc->vptr->string_value(sc->vptr->pair_car(args));
      printf("%s", str);
    }
  }
  return sc->NIL;
}

// square -- scheme function
// Example: (square 3)
pointer square(scheme *sc, pointer args) {
  if (args!=sc->NIL) {
    if(sc->vptr->is_number(sc->vptr->pair_car(args))) {
      double v=sc->vptr->rvalue(sc->vptr->pair_car(args));
      return sc->vptr->mk_real(sc,v*v);
    }
  }
  return sc->NIL;
}


int main(void) {
  scheme *sc;
 
  // Init Scheme interpreter
  sc = scheme_init_new();
 
  // Load init.scm
  FILE *finit = fopen("init.scm", "r");
  scheme_load_file(sc, finit);
  fclose(finit);

  // Define square
  sc->vptr->scheme_define(
       sc,
       sc->global_env,
       sc->vptr->mk_symbol(sc, "square"),
       sc->vptr->mk_foreign_func(sc, square));

  // Define display
  sc->vptr->scheme_define(
       sc,
       sc->global_env,
       sc->vptr->mk_symbol(sc, "display"),
       sc->vptr->mk_foreign_func(sc, display));

  // Run first example
  char *hello_scm = "(display \"Hello, world!\\n\")";
  scheme_load_string(sc, hello_scm);

  // Run second example
  char *square_scm = "(display "
                     "  (string-append \"Answer: \" "
                     "    (number->string (square 6.480740698407859)) \"\\n\"))";
  scheme_load_string(sc, square_scm);
 
  // Bye!
  scheme_deinit(sc);
  return 0;
}

Output

jrs@laptop:~/tinyscheme/tinyscheme-1.41$ time ./tshello
Hello, world!
Answer: 42.0

real   0m0.017s
user   0m0.016s
sys   0m0.000s
jrs@laptop:~/tinyscheme/tinyscheme-1.41$

My interest in timing this wasn't to see how fast it could display Hello, world! or the square root of 6.480740698407859 but how long it took to load the init.scm support library which is a decent size file for a Scheme script.


.
« Last Edit: August 24, 2014, 06:35:09 PM by John »

JRS

  • Guest
TinyScheme
« Reply #2 on: August 23, 2014, 10:18:33 PM »
Here is the beginning of the Script BASIC TinyScheme (TS) extension module. I think one of the coolest thing about TinyScheme is the mk_foreign_func that creates symbols on the fly in C. The init.scm also loads a set of default functions that smooths over many of the shortcomings of Scheme.

tshello.sb
Code: [Select]
' Tiny Scheme - extension module example

DECLARE SUB InitNew ALIAS "TS_init_new" LIB "ts"
DECLARE SUB Deinit ALIAS "TS_deinit" LIB "ts"
DECLARE SUB LoadStr ALIAS "TS_load_string" LIB "ts"

sc = InitNew()
LoadStr(sc, "(display \"Hello, world!\n\")")
Deinit(sc)

Output

jrs@laptop:~/sb/sb22/sblisp$ time scriba tshello.sb
Hello, world!

real   0m0.005s
user   0m0.008s
sys   0m0.000s
jrs@laptop:~/sb/sb22/sblisp$


TS ext. module interface file
Code: [Select]
// Tiny Scheme - Script BASIC extension module

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <time.h>
#include "../../basext.h"
#include "cbasic.h"

#define USE_INTERFACE 1

#include "scheme.h"
#include "scheme-private.h"


pointer display(scheme *sc, pointer args) {
  if (args!=sc->NIL) {
    if (sc->vptr->is_string(sc->vptr->pair_car(args)))  {
      char *str = sc->vptr->string_value(sc->vptr->pair_car(args));
      printf("%s", str);
    }
  }
  return sc->NIL;
}


/****************************
 Extension Module Functions
****************************/

besVERSION_NEGOTIATE
  RETURN_FUNCTION((int)INTERFACE_VERSION);
besEND

besSUB_START
  DIM AS long *p;
  besMODULEPOINTER = besALLOC(sizeof(long));
  IF (besMODULEPOINTER EQ NULL) THEN_DO RETURN_FUNCTION(0);
  p = (long*)besMODULEPOINTER;
  RETURN_FUNCTION(0);
besEND

besSUB_FINISH
  DIM AS long *p;
  p = (long*)besMODULEPOINTER;
  IF (p EQ NULL) THEN_DO RETURN_FUNCTION(0);
  RETURN_FUNCTION(0);
besEND


/***********************
 Tiny Scheme Functions
***********************/

besFUNCTION(TS_init_new)
  DIM AS scheme PTR sc;
  sc = scheme_init_new();
  sc->vptr->scheme_define(
     sc,
     sc->global_env,
     sc->vptr->mk_symbol(sc, "display"),
     sc->vptr->mk_foreign_func(sc, display));
  besRETURN_LONG(sc);
besEND

besFUNCTION(TS_deinit)
  DIM AS scheme PTR sc;
  besARGUMENTS("i")
    AT sc
  besARGEND
  scheme_deinit(sc);
  besRETURNVALUE = NULL;
besEND
 
besFUNCTION(TS_load_string) 
  DIM AS scheme PTR sc;
  DIM AS char PTR cmdstr;
  besARGUMENTS("iz")
    AT sc, AT cmdstr
  besARGEND
  scheme_load_string(sc, cmdstr); 
  besRETURNVALUE = NULL;
besEND
« Last Edit: August 24, 2014, 06:34:52 PM by John »

JRS

  • Guest
TinyScheme
« Reply #3 on: August 24, 2014, 01:06:26 PM »
Rob,

Would you mind giving TinyScheme a spin if you can find some time? I'm working on a Script BASIC extension module for it and a review by you before completion would be great. TS is used in GIMP as its scripting engine.

« Last Edit: August 24, 2014, 06:34:30 PM by John »

JRS

  • Guest
TinyScheme
« Reply #4 on: August 24, 2014, 03:31:17 PM »
Rob,

I noticed that the version of TinyScheme (1.39) wasn't built with MinGW and was pretty old. I rebuilt the scheme.exe with current source. The SB TS ext. module for Windows will use the 1.41 code you will be testing. (see attached)

TinyScheme Windows 32 & Ubuntu 64 console interpreters attached.

.
« Last Edit: August 24, 2014, 06:34:13 PM by John »

JRS

  • Guest
Re: TinyScheme
« Reply #5 on: August 24, 2014, 07:30:39 PM »
Rob,

I thought I would give your BL Mandelbrot script a try in TinyScheme. TS doesn't seem to like sequence.

Code: [Select]
jrs@laptop:~/tinyscheme/tinyscheme-1.41$ ./scheme
TinyScheme 1.41
ts> (define grid '())

(define mapped-grid '())



(define modulus

  (lambda (n d)

     (let (( r (floor (/ n d))))

      (- n (* r d)))))



(define cadr

    (lambda (L)

      (car (cdr L))))



(define sqrt

     (lambda (x)

       (exp (/ (log x) 2))))



(define sq (lambda(x) (* x x)))



(define 1- (lambda (x) (- x 1)))

(define 1+ (lambda (x) (+ x 1)))



(define level

 (lambda (i x y rc ic it orb)

  (if (or (= i it) (> orb 4)) i

    (level (1+ i) (+ rc (- (sq x) (sq y))) (+ ic (* 2 x y)) rc ic it (+ (sq x) (sq y))))))



(define mlevel

   (lambda (L)

     (level 0 (cadr L) (car L) (cadr L) (car L) 11 0)))



(define fill-grid

   (lambda (nrx xo dx nry yo dy matrix dup)

       (if (and (= 0 nrx) (= 0 nry)) matrix

         (if (= 0 nry) (fill-grid (1- nrx) xo dx dup yo dy matrix dup)

           (fill-grid nrx xo dx (1- nry) yo dy

            (cons (list (+ xo (* nrx dx)) (+ yo (* nry dy))) matrix) dup)))))



(define square-grid

   (lambda (nr x y dz)

     (fill-grid (1- nr) (+ x dz) dz nr y dz '() nr)))



(define map-grid

   (lambda (L)

     (map mlevel L)))



(define print*

  (lambda (x)

    (if (> x 9)

      (print x)

      (sequence (print x) (print '" ")) )))



(define print-grid

   (lambda (i it L)

     (if (null? L) T

       (if (= i it) (sequence (print* (car L)) (newline) (print-grid 0 it L))

         (sequence (print* (car L)) (print-grid (1+ i) it (cdr L)))))))



(define main

  (lambda ()

    (set! grid (square-grid 30 -1.7 -2.3 0.1))

    (set! mapped-grid (map-grid grid))

    (print-grid 0 30 mapped-grid)

))grid
ts> mapped-grid
ts> modulus
ts> cadr
ts> sqrt
ts> sq
ts> 1-
ts> 1+
ts> level
ts> mlevel
ts> fill-grid
ts> square-grid
ts> map-grid
ts> print*
ts> print-grid
ts> (main)
main
ts> Error: eval: unbound variable: sequence

JRS

  • Guest
Re: TinyScheme
« Reply #6 on: August 24, 2014, 09:26:28 PM »
I found this TS embedding (in C) example that emulates a prompted lisp tutorial. I had to add the simulated (quit) logic.

Code: [Select]
/**
 *  hello-scheme for illustration how to embed
 *  the tiny scheme interpreter in a C program
 *
 *  2012, OL
 */

#include <stdio.h>
#include <string.h>
#include "scheme.h"
#include "dynload.h"


/* scheme_load_string does not like
   carriage returns so strip them out */
void strip_cr( char *p, int max_len )
{
  int i;

  for( i=0; i < max_len && p[i]!='\0'; ++i )
    ;

  if( i > 0 && p[i-1]=='\n' )
    p[i-1] = '\0';
}


/**
 * illustration of a C function binding
 */
pointer func1(scheme *sc, pointer args)
{
  pointer arg;
  pointer retval;
  char    *strarg;
  double  realnumber;
  int     intnumber;
  int     i = 1;

  while( args != sc->NIL )
  {
    if( is_string( arg = pair_car(args)) )
    {
      strarg = string_value( arg );
      printf( "argument %d is string %s\n", i++, strarg );
    }
    else if( is_real( arg = pair_car(args) ) )
    {
      realnumber = rvalue( arg );
      printf( "argument %d is real number %lf\n", i++, realnumber );
    }
    else if( is_integer( arg = pair_car(args) ) )
    {
      intnumber = ivalue( arg );
      printf( "argument %d is integer number %d\n", i++, intnumber );
    }

    args = pair_cdr( args );
  }

  if( i > 1 )
    retval = sc -> T;
  else
    retval = sc -> F;

  return(retval);
}


/*
 * Simple REPL
 */
int main( int argc, char* argv[] )
{
  scheme sc;

  char   cmd_str[80];


  /* intialize the scheme object */
  if( !scheme_init(&sc) ) {
    fprintf(stderr,"Could not initialize!\n");
    return 2;
  }

  /* set standard input and output ports */
  scheme_set_input_port_file(&sc, stdin);
  scheme_set_output_port_file(&sc, stdout);


  /* illustration how to define a "foreign" function
     implemented in C */
  scheme_define(&sc,sc.global_env,mk_symbol(&sc,"func1"),mk_foreign_func(&sc, func1));


  puts("Tiny Scheme REPL:");
  puts("try e.g. the following commands:");
  puts("   (write (+ 1 2))");
  puts("   (func1 \"hello\" 42 1.24)\n");

  do {
    printf("\n>");
    fgets( cmd_str, 80, stdin );
    strip_cr( cmd_str, 80 );
    if (strncmp(cmd_str,"(quit)",6)==0) break;
    scheme_load_string( &sc, cmd_str );
  } while(1);


  scheme_deinit(&sc);

  return 0;
}

Output

jrs@laptop:~/tinyscheme/tinyscheme-1.41$ ./testscm
Tiny Scheme REPL:
try e.g. the following commands:
   (write (+ 1 2))
   (func1 "hello" 42 1.24)


>(write (+ 1 2))
3
>(func1 "hello" 42 1.24)
argument 1 is string hello
argument 2 is integer number 42
argument 3 is real number 1.240000

>(quit)
jrs@laptop:~/tinyscheme/tinyscheme-1.41$

JRS

  • Guest
Re: TinyScheme
« Reply #7 on: August 24, 2014, 10:46:45 PM »
I added the scheme_set_output_port_file(sc, stdout); TS function call to output more that just Display related responses. This TS extension module is basically functional with 3 calls to TinyScheme.  8)

Code: [Select]
' Tiny Scheme - extension module example

DECLARE SUB InitNew ALIAS "TS_init_new" LIB "ts"
DECLARE SUB Deinit ALIAS "TS_deinit" LIB "ts"
DECLARE SUB LoadStr ALIAS "TS_load_string" LIB "ts"

sc = InitNew()
LoadStr sc, "(write (+ 2 2)) (newline)"
Deinit sc

Output

jrs@laptop:~/sb/sb22/sblisp$ scriba tshello.sb
4
jrs@laptop:~/sb/sb22/sblisp$

RobbeK

  • Guest
Re: TinyScheme
« Reply #8 on: August 24, 2014, 11:46:26 PM »
Hi John,

Downloaded, I'll convert the Mandelb for TinyScm --  (sequence ) is (begin ) in the R5RS standard. (and iirc (print ) should become (display ) )

best Rob

JRS

  • Guest
Re: TinyScheme
« Reply #9 on: August 24, 2014, 11:54:38 PM »
Thanks Rob.

After the change, print is complaining.

Code: [Select]
jrs@laptop:~/tinyscheme/tinyscheme-1.41$ ./scheme
TinyScheme 1.41
ts> (load "mbrot.scm")
Loading mbrot.scm
Error: (mbrot.scm : 64) eval: unbound variable: print
jrs@laptop:~/tinyscheme/tinyscheme-1.41$

JRS

  • Guest
Re: TinyScheme
« Reply #10 on: August 25, 2014, 12:06:10 AM »
I'll just wait until you post something. You may find a better way in TS.


RobbeK

  • Guest
Re: TinyScheme
« Reply #11 on: August 25, 2014, 12:13:29 AM »
Change (print ) into (display ) -- I'll convert using iteration on some parts

best Rob

JRS

  • Guest
Re: TinyScheme
« Reply #12 on: August 25, 2014, 12:20:37 AM »
Nope. Still doesn't work. The only print left is print-grid.

(write  worked for me in my ext. module test.

RobbeK

  • Guest
Re: TinyScheme
« Reply #13 on: August 25, 2014, 12:25:34 AM »
John,

working on it --  the prints in definitions must remain (print-grid ) (print* ) etc...  (only the solitaire print must be replaced )

Rob

JRS

  • Guest
Re: TinyScheme
« Reply #14 on: August 25, 2014, 12:31:13 AM »
Got it to work. (changed wrong program  >:( ) Still throws an error. Much faster than BL.

Code: [Select]
jrs@laptop:~/tinyscheme/tinyscheme-1.41$ time ./scheme mbrot.scm
1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1
1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1
1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1
1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 1
1 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 1
1 1 1 1 1 1 2 2 2 3 3 3 3 3 3 3 3 4 4 4 115 4 4 3 3 2 2 2 2 1
1 1 1 1 1 2 2 2 3 3 3 3 3 3 3 3 4 4 4 5 7 9 114 4 3 3 2 2 2 1
1 1 1 1 1 2 3 3 3 3 3 3 3 3 4 4 4 4 5 6 9 118 5 4 4 3 3 3 2 1
1 1 1 1 2 3 3 3 3 3 3 3 3 4 4 4 4 5 6 8 1111116 5 5 4 3 3 3 1
1 1 1 1 2 3 3 3 3 3 3 3 4 4 4 5 7 8 8 101111119 6 6 5 4 3 3 1
1 1 1 2 3 3 3 3 3 3 3 4 4 5 5 6 11111111111111111111114 3 3 1
1 1 1 2 3 3 3 3 3 4 5 5 5 5 6 8 111111111111111111117 5 3 3 1
1 1 1 3 3 3 3 4 5 7 7 7 7 7 7 11111111111111111111119 5 4 3 1
1 1 1 3 4 4 4 5 5 7 111111119 1111111111111111111111116 4 3 1
1 1 1 4 4 4 5 5 6 8 11111111111111111111111111111111115 4 3 1
1 1 1 4 4 6 6 7 1111111111111111111111111111111111118 5 4 3 1
1 1 1111111111111111111111111111111111111111111111117 5 4 3 1
1 1 1 4 4 6 6 7 1111111111111111111111111111111111118 5 4 3 1
1 1 1 4 4 4 5 5 6 8 11111111111111111111111111111111115 4 3 1
1 1 1 3 4 4 4 5 5 7 111111119 1111111111111111111111116 4 3 1
1 1 1 3 3 3 3 4 5 7 7 7 7 7 7 11111111111111111111119 5 4 3 1
1 1 1 2 3 3 3 3 3 4 5 5 5 5 6 8 111111111111111111117 5 3 3 1
1 1 1 2 3 3 3 3 3 3 3 4 4 5 5 6 11111111111111111111114 3 3 1
1 1 1 1 2 3 3 3 3 3 3 3 4 4 4 5 7 8 8 101111119 6 6 5 4 3 3 1
1 1 1 1 2 3 3 3 3 3 3 3 3 4 4 4 4 5 6 8 1111116 5 5 4 3 3 3 1
1 1 1 1 1 2 3 3 3 3 3 3 3 3 4 4 4 4 5 6 9 118 5 4 4 3 3 3 2 1
1 1 1 1 1 2 2 2 3 3 3 3 3 3 3 3 4 4 4 5 7 9 114 4 3 3 2 2 2 1
1 1 1 1 1 1 2 2 2 3 3 3 3 3 3 3 3 4 4 4 115 4 4 3 3 2 2 2 2 1
1 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 1
1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 Error: (mbrot.scm : 64) eval: unbound variable: t
Errors encountered reading mbrot.scm

real 0m2.293s
user 0m2.288s
sys 0m0.000s
jrs@laptop:~/tinyscheme/tinyscheme-1.41$