Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

What Scheme does /prog/ use?

Name: Anonymous 2012-01-28 22:31

I have been using Chicken for a little bit. Used Racket for like 5 minutes. R6RS is PIG DISGUSTING!

That is all.

Name: Anonymous 2012-01-28 22:32

chicken when I'm doing call/cc stuff. scm otherwise.

Name: Anonymous 2012-01-28 22:34

javascript

Name: Anonymous 2012-01-28 22:41

javascheme

Name: Anonymous 2012-01-28 23:17

schemescript

Name: Anonymous 2012-01-29 0:08

I wrote my own. It supports all the features I need.

Name: Anonymous 2012-01-29 2:07

>>6
I want to be a cool hacker like you.

Name: Anonymous 2012-01-29 7:43

>>7
Well then write your own. It's not hard and it's a lot of fun. In fact, programming a Scheme interpreter in C is a lot like programming in Scheme once all the basic abstractions are laid out. Start with a basic generic object type.

typedef struct object {
    int type;
    union {
        struct {
            object *car;
            object *cdr;
        } pair;
        char *symbol;
        char *string;
        double number; /* or implement bignums if you want */
        ...
    } val;
} object;


Now write cons, car, cdr, symbol, string, number, etc. and you're ready to the write the parser.

Since code is data in Scheme, you can write a parser that simply translates text to data and not worry about executing it. Write it just like you would a recursive function in Scheme. The parse takes a "list" (either an array of chars or a FILE stream) and returns a tree (of objects) that represent the code as data.

You should also write display concurrently so you can have display(parse(stdin)); in your main loop until the parser is completed. Once the output is equivalent to the input, you're ready to move on.

Next step is eval. Once you have your generic Scheme object and all the necessary primitive-like constructors, predicates, accessors and mutators, you could translate the metacircular evaluator from SICP to C in a few hours. The MCE is not that elegant, however, and will certainly be slow as balls. The way it stores the environment for instance is too complex and can be greatly simplified. Primitive and compound procedures are better represented as native C structs contained in object rather than "tagged lists". MCE's eval however is a good starting point for learning how to implement the define, lambda, and if special forms.

Next, write apply. Binding primitives to your application will be time consuming and tedious, but it's rewarding once your able to start running real Scheme programs. Read R5RS for implementation details.

At this point, you can either write special forms for and, or, cond, let, begin, etc. or you can just implement define-syntax and do the rest in Scheme. It all depends on whether you want a pure C implementation or just a tiny C core. Both have pros and cons (no pun, etc. etc.).

Good luck.

Name: Anonymous 2012-01-29 10:14

>>8
An actual informative post on /prog/? I commend you.

Name: Anonymous 2012-01-29 11:20

chicken lyf

Name: Anonymous 2012-01-29 13:09

>>8
I'd argue that a bytecode (stack machine) compiler would be easier to write.  Your move.

Name: Anonymous 2012-01-29 13:15

>>11
A bytecode(stack machine) isn't the same thing as a compiler.

Name: Anonymous 2012-01-29 13:17

NO U. GAME OVER U STUPID KID!!!

Name: FAGGOT 2012-01-29 13:19

I am FAGGOT. Fuck me.

Name: Anonymous 2012-01-29 13:25

keep fucking that chicken

Name: Anonymous 2012-01-29 13:29

>>15
Don't be j.

Name: Anonymous 2012-01-29 14:16

>>8,11

Here is my, pathological, scheme object scheme for 32-bit systems. This is pretty standard for most C-based implementations of scheme, and possibly, most LISPs for that matter. Notice the use of the struct hack and the size field in the manifest. This makes the compacting GC's job simpler in reckoning with objects on the heap, while placing on the allocator the burden of calculating and recording the size of each object.

typedef struct obj
{
    //manifest
    struct {
        unsigned int type   : 5;
        unsigned int gc     : 1;
        unsigned int vec    : 1;
        unsigned int pad    : 9;
        unsigned int size   : 16;
    };
    union
    {
        struct obj     *l;
        signed int      i;
        float           f;
        char            c;
    } datum[0];
} obj;

Name: Anonymous 2012-01-29 14:21

>>17
sexp

Name: Anonymous 2012-01-29 14:42

>>17
if you swap the l and the f you get: THE FORCED INDENTATION OF LISP CODE

:3

Name: Anonymous 2012-01-29 16:06

>>17
datum[0]
If you're making it variable sized, why use a hack like that? Instead use arrays directly and follow the convention that the first element in every array is the manifest.


union obj
{
    struct {
        unsigned int type   : 5;
        unsigned int gc     : 1;
        unsigned int vec    : 1;
        unsigned int pad    : 9;
        unsigned int size   : 16;
    }           manifest;
    union obj  *l;
    signed int  i;
    float       f;
    char        c;
};

Name: Anonymous 2012-01-29 16:31

>>20

Because, I found it easier to read and reason about, as I was writing it. However, I wouldn't imagine there's really any difference, at all.

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List