Live data from Hacker News

Lisp in fewer than 200 lines of C

carld.github.io

61–70 of 108 posts

Re: Lisp in fewer than 200 lines of C

#61
post #33

Writing your own Lisp-ette is a brilliant evening or weekend project, regardless of the language. It's some of the simplest non-toy parsing you can attempt, a bit of light data structure work, and understanding eval/apply is 80% of the work in implementing it. I would highly recommend anyone to have a go, and try not to follow existing code too closely: figure out the problems in your language of choice. The post ide…

Lexical scoping is essential if you want to use the Lisp for anything essential. If you start with dynamic scope for everything and the system develops any real complexity, then switching to lexical scoping becomes very painful. Best to do it right the first time.

Re: Lisp in fewer than 200 lines of C

#62

If you like this, you might like Lisp interpreter written in assembly in a single file. It is one of the best commented code ever written imo. https://github.com/marcpaq/arpilisp

It seems like arpilisp is inspired by jonesforth[0]. Although not directly stated, the style is similar and the acknowledgements mentions Richard Jones. Anyone interested in implementing simple programming languages might also want to take a look at jonesforth.

[0]: https://github.com/nornagon/jonesforth

Re: Lisp in fewer than 200 lines of C

#63

Oof, all the macros are broken: #define is_space(x) (x == ' ' || x == '\n') #define is_parens(x) (x == '(' || x == ')') Should be #define is_space(x) ((x) == ' ' || (x) == '\n') #define is_parens(x) ((x) == '(' || (x) == ')') Probably doesn’t matter in practice for this. It could end up being a nasty source of bug later on in the project.

That still evaluates x twice, which can also be a source of bugs. I usually take one of two approaches: either decide that this is a weekend hack and using the macros whenever the expansion isn't obvious in my head is a sign of too much complexity, or use this GCC extension:

    #define is_space(x) ({ typeof(x) y = x; y == ' ' || y = '\n'; })
(Or in this case, turn it into an actual function and let the compiler figure out optimization.)

Re: Lisp in fewer than 200 lines of C

#64
post #33

Writing your own Lisp-ette is a brilliant evening or weekend project, regardless of the language. It's some of the simplest non-toy parsing you can attempt, a bit of light data structure work, and understanding eval/apply is 80% of the work in implementing it. I would highly recommend anyone to have a go, and try not to follow existing code too closely: figure out the problems in your language of choice. The post ide…

Agree.

I'm writing Scheme R5RS in Kotlin (https://github.com/kovrik/scheme-in-kotlin) and have implemented everything except macros (6).

Have no idea how to beat them.

Re: Lisp in fewer than 200 lines of C

#65
Toward the end of `print_obj()`, we see:

        if (is_pair(cdr(ob))) {
          printf(" ");
          print_obj(cdr(ob), 0);
        }
How could this `if` statement ever evaluate to false? We already verified that `cdr(ob) != 0`, and the CDR can never be a plain old string, so isn't this `if` superfluous?

Re: Lisp in fewer than 200 lines of C

#66
post #64
post #33

Writing your own Lisp-ette is a brilliant evening or weekend project, regardless of the language. It's some of the simplest non-toy parsing you can attempt, a bit of light data structure work, and understanding eval/apply is 80% of the work in implementing it. I would highly recommend anyone to have a go, and try not to follow existing code too closely: figure out the problems in your language of choice. The post ide…

Agree. I'm writing Scheme R5RS in Kotlin ( https://github.com/kovrik/scheme-in-kotlin ) and have implemented everything except macros (6). Have no idea how to beat them.

Just think of them as defining functions that take s expressions in and spit s expressions out before “normal” runtime evaluation and which hence only see built in symbols.

Re: Lisp in fewer than 200 lines of C

#67

If you like this, you might like Lisp interpreter written in assembly in a single file. It is one of the best commented code ever written imo. https://github.com/marcpaq/arpilisp

Since this is written in assembly is it much faster than a C version since this one can manage its own stack frames and stack variables and such? I always imagined that’s the case and that a lisp implemented fully in assembly would be the trick to a super fast lisp that can complete with Go.

Re: Lisp in fewer than 200 lines of C

#68
post #63

Oof, all the macros are broken: #define is_space(x) (x == ' ' || x == '\n') #define is_parens(x) (x == '(' || x == ')') Should be #define is_space(x) ((x) == ' ' || (x) == '\n') #define is_parens(x) ((x) == '(' || (x) == ')') Probably doesn’t matter in practice for this. It could end up being a nasty source of bug later on in the project.

That still evaluates x twice, which can also be a source of bugs. I usually take one of two approaches: either decide that this is a weekend hack and using the macros whenever the expansion isn't obvious in my head is a sign of too much complexity, or use this GCC extension: #define is_space(x) ({ typeof(x) y = x; y == ' ' || y = '\n'; }) (Or in this case, turn it into an actual function and let the compiler figure o…

GCC extensions make my brain hurt :( Should just use C++ at that point:

    template
    bool is_space(const T & x) {
        return x == ‘ ‘ || x == ‘\n’;
    }

Re: Lisp in fewer than 200 lines of C

#69
post #64

Earlier quoted context omitted.

Agree. I'm writing Scheme R5RS in Kotlin ( https://github.com/kovrik/scheme-in-kotlin ) and have implemented everything except macros (6). Have no idea how to beat them.

Just think of them as defining functions that take s expressions in and spit s expressions out before “normal” runtime evaluation and which hence only see built in symbols.

Yes, I get that (in general).

But then there are things like hygiene, performance and some tricky edge-cases.

And I couldn't find any standard (and simple) algorithm to implement macros (preferably written in something other than Scheme itself).

Still trying to wrap my head around.

Re: Lisp in fewer than 200 lines of C

#70

If you like this, you might like Lisp interpreter written in assembly in a single file. It is one of the best commented code ever written imo. https://github.com/marcpaq/arpilisp

Since this is written in assembly is it much faster than a C version since this one can manage its own stack frames and stack variables and such? I always imagined that’s the case and that a lisp implemented fully in assembly would be the trick to a super fast lisp that can complete with Go.

LISP was created a long time ago. Assembly was the weapon of choice. Thinking Machines, Symbolics and Macsyma might already say: We did that. But, uh, no.
Post reply on HN