Writing/understanding a lisp interpreter is a longstanding item on my TODO list. Question: how do I go from tackling this to tackling compilers?
I was just recommended "Lisp in Small Pieces" for just this.
Mal – Make a Lisp, in 68 languages
21–30 of 74 posts
Re: Mal – Make a Lisp, in 68 languages
#22Also, writing a Lisp in a purely functional language isn't the best :X Things like by-reference function environments and atoms are hard to implement if you're not Haskell, at least if you try in the method that the guide outlines...
Re: Mal – Make a Lisp, in 68 languages
#23Earlier quoted context omitted.
While we're at it, why don't we replace high school math tests with one question: "Solve the Riemann hypothesis". We can replace the physics curriculum with "Unify quantum mechanics with general relativity", and throw out computing courses in favour of "Prove whether or not P = NP". It's important to re-do things which others have already worked out, in order to reach a greater understanding :)
Whatever. I learned how to implement Lisp by reading the source code for multiple compilers. Started with Franz Lisp, then KCL and CMUCL. I don't feel that a toy interpreter is going to teach the same things.
Re: Mal – Make a Lisp, in 68 languages
#24Earlier quoted context omitted.
Whatever. I learned how to implement Lisp by reading the source code for multiple compilers. Started with Franz Lisp, then KCL and CMUCL. I don't feel that a toy interpreter is going to teach the same things.
everyone learns in different ways, don't be too attached to your own perspective. we all interpret the world through different lenses and need to learn through the expressions of different methodologies. some people benefit heavily by implementing something themselves and not just reading through something someone else wrote. some people feed off of that practical and robust experience of implementation in order to g…
Re: Mal – Make a Lisp, in 68 languages
#25Re: Mal – Make a Lisp, in 68 languages
#26Could someone explain this gem in the C version? https://github.com/kanaka/mal/blob/master/c/types.c#L170
http://www.kylheku.com/cgit/txr/tree/lib.c#n5525
These functions are only used from within C code; they are not the basis for any intrinsic functions. The call to each of these functions knows exactly the type of function it wants to make.
There is a notation in the naming.
Firstly, the leading 'f' denotes functions with an environment value, whereas 'n' denotes non-environment functions. Then there is a number indicating the number of arguments. Then an optional letter which is 'o' if the function has optional arguments, or 'v' if it is variadic. Both can be present in which case we have 'ov.
Thus for example func_n2ov(some_c_function, 1) will create a variadic function with 2 fixed arguments, of which 1 is required (so one optional). some_c_function has to have the type signature val (* )(val, val, varg). No casting is required because func_n2ov just assigns this to the correct union member. If we pass a function with an incorrect signature, we get a C compile error.
The func_n2ov constructor is used when registering the unique function in eval.c:
reg_fun(intern(lit("unique"), user_package), func_n2ov(unique, 1));
We intern the string "unique" in the user package ("usr"), and use that symbol to register a function createdy by hoisting the C function unique into the Lisp domain with func_n2ov.I wrote TXR in a way that is easy to understand and maintain. It is only implemented in C, though. If you want to study how to make a Lisp interpreter in C. Yet, it is production code for real work.
Re: Mal – Make a Lisp, in 68 languages
#27Earlier quoted context omitted.
In struct MalVal[0], the values f0 through f20, where each holds a pointer-to-functions of the corresponding arity, live in a big (multifacted?) union. Using arg_cnt, the switch assigns func to the appropriate value in mv->val using the appropriate cast. For example, when arg_cnt is 2, mv->val.f2 receives func converted to void * (* )(void* , void* ), that is, pointer to a function that accepts two parameters of type…
This could be made massively less ugly and more readable by typedef'ing the function pointer types by the way. Then one could just write: case 13: mv->val.f13 = (F13)func; break; As a C programmer I got to say people in general don't use typedef for function pointer types often enough. The types are so ugly and verbose, they should be typedef'ed by default.
Re: Mal – Make a Lisp, in 68 languages
#28Earlier quoted context omitted.
In struct MalVal[0], the values f0 through f20, where each holds a pointer-to-functions of the corresponding arity, live in a big (multifacted?) union. Using arg_cnt, the switch assigns func to the appropriate value in mv->val using the appropriate cast. For example, when arg_cnt is 2, mv->val.f2 receives func converted to void * (* )(void* , void* ), that is, pointer to a function that accepts two parameters of type…
This could be made massively less ugly and more readable by typedef'ing the function pointer types by the way. Then one could just write: case 13: mv->val.f13 = (F13)func; break; As a C programmer I got to say people in general don't use typedef for function pointer types often enough. The types are so ugly and verbose, they should be typedef'ed by default.
Re: Mal – Make a Lisp, in 68 languages
#29Re: Mal – Make a Lisp, in 68 languages
#30There is a similar project called "Build Your Own Lisp"[0] (BYOL), which is a book that walks one through making a Lisp in C. Has anybody here done BYOL? How does it compare to MAL? If you had to choose one to learn how to create a Lisp, which would you choose? [0]: http://www.buildyourownlisp.com/