Live data from Hacker News

Lisp in fewer than 200 lines of C

carld.github.io

81–90 of 108 posts

Re: Lisp in fewer than 200 lines of C

#81
post #69

Earlier quoted context omitted.

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.

"This paper describes a modified form of Kohlbecker’s algo- rithm for reliably hygienic (capture-free) macro expansion in block-structured languages, where macros are source-to- source transformations specified using a high-level pattern language."

http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.464...

Re: Lisp in fewer than 200 lines of C

#82
post #63

Earlier quoted context omitted.

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’; }

Even better if you make it:

    template
    constexpr bool is_space(const T & x) {
        return x == ' ' || x == '\n';
    }
Debuggable, type safe and same performance as straight C code.

Re: Lisp in fewer than 200 lines of C

#83

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

Someone once suggested to me the easiest way to "bootstrap the world" is to write a Forth implementation in assembly, and then write your Lisp in Forth.

Re: Lisp in fewer than 200 lines of C

#85
post #76

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.

I'd argue that is_space() should be isspace(), the standard from . Pretty sure it wouldn't make the semantics of the language worse, but it's one less wheel re-invented and makes the code a smidgen easier to read since there's one less concept to learn in it. Also one less thing to debug ...

Heh. Make that , of course. D'oh. :)

Re: Lisp in fewer than 200 lines of C

#86
post #82

Earlier quoted context omitted.

GCC extensions make my brain hurt :( Should just use C++ at that point: template bool is_space(const T & x) { return x == ‘ ‘ || x == ‘\n’; }

Even better if you make it: template constexpr bool is_space(const T & x) { return x == ' ' || x == '\n'; } Debuggable, type safe and same performance as straight C code.

And throw an `inline` in there just to be more likely to end up with something macro-like.

Re: Lisp in fewer than 200 lines of C

#87
post #82

Earlier quoted context omitted.

Even better if you make it: template constexpr bool is_space(const T & x) { return x == ' ' || x == '\n'; } Debuggable, type safe and same performance as straight C code.

And throw an `inline` in there just to be more likely to end up with something macro-like.

`constexpr` is implicitly `inline`: http://en.cppreference.com/w/cpp/language/inline

Re: Lisp in fewer than 200 lines of C

#88
post #82

Earlier quoted context omitted.

GCC extensions make my brain hurt :( Should just use C++ at that point: template bool is_space(const T & x) { return x == ‘ ‘ || x == ‘\n’; }

Even better if you make it: template constexpr bool is_space(const T & x) { return x == ' ' || x == '\n'; } Debuggable, type safe and same performance as straight C code.

Constexpr is not necessary. Only required if you want to ensure that a variable is initialized with a pre-computed value. The compiler will optimize in either case if it can, regardless of the constexpr attribute.

Re: Lisp in fewer than 200 lines of C

#89
post #72

Earlier quoted context omitted.

Another fun one is a Forth interpreter. I tried to make one in Rust once, I can't say I actually succeeded but it's fun to tinker with. It is simple enough that you can probably write a bad one in assembly without that much assembly knowledge.

Or Brainfuck. It's fun and only takes half an hour or so.

Not sure why you're downvoted (people don't like swear words?). As a "my first interpreter" project Brainfuck is really quick, fun and could motivate you to explore the topic further.

Re: Lisp in fewer than 200 lines of C

#90
post #82

Earlier quoted context omitted.

Even better if you make it: template constexpr bool is_space(const T & x) { return x == ' ' || x == '\n'; } Debuggable, type safe and same performance as straight C code.

Constexpr is not necessary. Only required if you want to ensure that a variable is initialized with a pre-computed value. The compiler will optimize in either case if it can, regardless of the constexpr attribute.

> Only required if you want to ensure that a variable is initialized with a pre-computed value

Yep.

Post reply on HN