xorvoid / forsp

Forsp: A Forth+Lisp Hybrid Lambda Calculus Language
MIT License
133 stars 16 forks source link

Add string syntax and parse word #4

Closed jakiki6 closed 3 months ago

jakiki6 commented 3 months ago
note: you have to escape \ with \\ and " with \"
note: print now checks whether the atom contains illegal characters and prints it as a string if it does

parse word: it has the signature of [atom offset -> atom new-offset object] to treat atom as a string and start reading an object at offset in the string and increment the offset on the stack and add the read object
xorvoid commented 3 months ago

I'd like to keep Forsp a minimalist language. To me it's more interesting that way than a full-featured one.

If people are really interested in adding a lot of core features, then I might suggest adding some sub-directory like "full-featured" that has much more. Or... creating a separate repo with different goals. Personally, I'm not sure I'm interested in building something out, but I encourage others to try if that interests them.

In response to your implementation: you probably want strings to be another object type, not an atom. It's implied that atoms are interned, and "eq" will work on them.

pmarreck commented 3 months ago

Maybe a directory named the-non-minimalist-parts?

I too would like to see what enhancements to this would look like, while also wanting the core to stay minimalist.

But having worked on a fork of another "minimalist-but-powerful" idea, es-shell https://github.com/pmarreck/es-shell (although sadly not recently- new job and new kid have halted my dev free time), I am unfortunately familiar with the complexity that can emerge when you're trying to merge your idea with non-minimalist changes to upstream. ;)

Not sure if a tweak to make things more "plugin-friendly" would make sense? Some mechanism where someone could add things like 1) new tokens, 2) new elements of state, 3) new root functions (of course), 4) new primitives and low-level primitives 5) new defines. I'm not a C dev by day, so I don't know what the "prior art" is with that idea... The goal would be to NOT (ideally) have to overwrite any of your existing core functions, by adding hooks somehow.

In theory, this should not be terribly complicated to implement, since the only state you really have to worry about is... a stack. Right? (Well, and the parser, and evaluator, and any new functions required...)

To test the mechanism out, you could try implementing a new feature (like... adding string syntax) using it... or... even writing a test for it... or something... (OK, what is it with C devs and a total lack of any test coverage? Unit testing is pretty much de-facto in most other languages at this point.)

Just some thoughts, sorry to stick them on a random PR! As a fan of Forth (which I started writing an interpreter for in Elixir, to the point that I can run things like a factorial function https://github.com/pmarreck/elixir-snippets/blob/master/rpn_forth_thing.exs) and Lisp (at least in theory... even if I stumbled in CS212 at Cornell, which was Scheme-based at the time), this project is nifty!

xorvoid commented 3 months ago

Well I was thinking just duplicating/forking the source elsewhere. The implementation is very minimalist/proof/of-concept. If you actually wanted to build out a real and practical language you'd have to do much more. E.g. Forsp doesn't even have a GC at the moment. And you'd want some semblance of imports/modules. And lots of additional types: strings, arrays, hash tables, etc. Then you might be adding threads and synchronization primitives. You probably would also want to do a compiled version and generate actually decent machine code. Trying to jam all of these (and more) into a minimalist language is, ummm, going to be a failure. Rather than doing one thing well, it'll be doing two things badly.

Personally, as stated above, my interests are around minimalist and bootstrapping languages. So, I don't have much drive to build out these kinds of things.

If a group of people really want to go down that road, I'll give you my blessing but it's probably a fork or a variant of some kind so the minimalist can remain here.

I would also suggest a strong vision/planning. You don't want to just jam random features in. Instead you should play around with like 5+ approaches and only accept the feature in when it actually feels right. (E.g. I wouldn't say the string impl here "feels" right).

jakiki6 commented 3 months ago

Yeah this string impl is just a hacked together way to generate atoms with otherwise invalid content. I thought about it and I had an idea. While you could implement strings in the language as a list of integers, that would waste a lot of spaces. That's why I think we should add a string type (could be just a plain array of bytes) and some basic functions like string-length, make-string (creates new zeroed out string of specified length), string-peek and string-poke (to copy between strings). Everything else including stuff like parse can be implemented in the language itself. Having parse allows you to create a kind of module system since you can dynamically load code.

I'm open for suggestions.

jakiki6 commented 3 months ago

I've added my POC implementation for my suggestion

pmarreck commented 3 months ago

lol @ last commit message. Whether or not original author agrees with this direction, always fun to see developer enthusiasm. But where are the tests? 😉

(also, is Forsp incredibly fast at this point due to being so simple? I want to play with it...)

jakiki6 commented 3 months ago

yeah I forgot I still had this PR

I'll close it now and work on it a bit more until it's polished (the GC is kinda broken with closures so the forsp.fp fails)