What's the point? No link to more detailed documentation that might explain why I would want to use this compared to the languages it says it took inspiration from.
Well it’d still be good to know why the author made it. Is it a toy language to learn about how to build a vm-interpreted language? Is it because the author can’t stand Python indentation. Or maybe there is a reason that clearly makes this interesting to use in the real world.
Because from the readme, it doesn’t look like this language brings anything to the table compared to Python/Node.
Is it? Irrespective of what I think of the post, I can't see any context in which posting it to a large forum full of strangers wouldn't count as 'promoting it'.
Maybe OP could phrase it a bit better, but i dont think its wrong to want some context. If its just for fun, that's definitely cool, but its also good to say that. Similarly, if there is something unique about the language, it would be nice to say that too.
Its not that the project has to be ground breaking or anything, just be nice to know what we're looking at.
I get asked this question a lot. My goal for this project is not to convince you to use it. This new language does _nothing_ that you couldn't find in other languages today. This project won't take over the world, and many people ask me what the point of it is. It's purely a project stemmed from curiosity with absolutely no capitalistic motives. I did it based on my years of self-directed research studying many incredible programming languages, and this is what I have to show for my research.
My motivation for this was to learn how to build a programming language with a grammar, virtual machine, and garbage collector. It's a hobby project, not intended to be used for business.
Show HN has its own rules and so forth but they are about posting work under the Show HN rubric. They aren't a requirement, though, you don't have to post personal work as a Show HN.
I just saw two screenshots and already don't like it. It seems its output sacrifices information for the sake of... tabulation? presentation? I don't know, but it's the wrong call.
Maybe it wasn't intended, but having that screenshot as the tool's showcase sends a message to me.
I don't think you have fully understood the screenshots. The first one shows an example source code, the second one shows the byte code generated from the source code of calling the print function. This is the bytecode that will be executed when the program is executed. It has nothing to do with the output of the program itself.
I understood them. Take a look at the constants table, indices 0, 2, 4, 6: the column "Value" is truncated. Now imagine you have trouble with an ana function and want to take a look at the generated bytecode. Would you rather have the columns perfected aligned and try to guess the loaded function name from its first letter? I see several HNers with downvote capacity would, which is a surprise...
Guilty as charged: https://klibert.pl/statics/awesome-taglist-shown.png - see `make_wibox_conta[iner, obviously]`. It happens when you don't want, or can't, compute the needed column width before printing. It's just a lot less code to pick a number and leave the formatting for later.
The same problem bit me multiple times when pretty-printing nested data structures. There's often an arbitrary limit to the depth the printer recurse to and/or the number of elements that get displayed, with the rest hidden behind "..." or something similar. No matter what number you pick, sooner or later you're going to get a case where you miss a really interesting/important piece of information because it got hidden. And if you try to change the default, you're going to get a case where you miss important info because you couldn't be bothered to scroll that far up...
Anyway: you're right, this is bad, but also pretty common. Though in this particular case it's really bad, because most of the column width is taken by irrelevant data. Replacing `<function '` with λ would already help a lot.
I can answer this. The biggest insight I've gained from going deep into language implementation is that primitive and fundamental concepts do not go away even if things are abstracted by high level features in high-level languages. For example, loops, jumps, will find themselves underlying in any language implementation regardless of the languages abstractions.
Do you mean for all imperative languages? Functional or declarative languages can do away with loops and jumps. Not trying to nitpick, perhaps you had some further insights when creating this
The functional language does do away with loops, but when the rubber nets the road, you don’t have any choice: somewhere, something will execute the equivalent of “for(int i = 0; i <= 10; i++) {}”.
When I implemented Mindcode, I realized that “while” is the basic construct and that all enumerations and looping compiled down into goto.
Mindcode is a Ruby-like language for the Mindustry game. Mindustry has an assembly-like language with a visual editor in-game. Mindcode has a more traditional text-based flow.
> somewhere, something will execute the equivalent of “for(int i = 0; i <= 10; i++)
Not necessarily; depending on what's going in in the loop, you can compile the code into parallel non-looping instructions that execute on multiple cores or threads. No loops needed.
It's a specific case but not a very specific case, and one that is becoming more common as core counts are exploding.
And anyway, even if it were a very specific case it's still an existence proof that disproves the assertions that "all that abstraction is being turned into loops and jumps." as one other poster put it. The replies here are speaking in very absolute terms ("you don’t have any choice", "loops and jumps cannot ever go away regardless of the higher level abstractions"), which are not true in an absolute sense.
The OP said:
> Do you mean for all imperative languages? Functional or declarative languages can do away with loops and jumps
And everyone here is answering them so far from the perspective of imperative languages. But depending on the program, it's not necessarily the general case in declarative languages, where we have much more freedom to compile things as we want, including without loops where they would be used in an imperative language.
Since this is a thread about language design and we're talking about alternative paradigms and how things get compiled to instructions, it's absolutely true that if our problem can be parallelized we don't have to loop at all. This is not a special case, but something that is generally applicable to many kinds of situations. Now that we're entering a world of potentially 1000s of cores available on consumer CPUs in the near future, what I'm saying is going to become the general case more and more.
If the iteration bounds are statically known (i.e. 0...10 in above example) you can avoid the loop by unrolling it, or using some kind of explicit parallelism, like SIMD for example.
In general, the iteration bounds aren't known and some kind of loop is required.
Totally reductionist on my part, but when you've written assembly by hand you realise that loops and jumps cannot ever go away regardless of the higher level abstractions.
At least I'm not aware of any CPUs that are not imperative in operation.
Most fp loop-like things are recursion. Traditional iterative loops are abstractions over goto. Arguably a function call is an abstraction of goto (JMP)+stack manipulation.
So they are both abstractions over goto, but i would say they are sibling abstractions not parent/child.
C was named in pre internet times. So I understand.
With go, they had to come up with a nickname for it (golang). So now the language has two names.
As a result, the typical "go <something>" and "golang <something>" search results will always be potentially imprecise, and partial (unless everybody in the world stops calling it "go" in favour of "golang".
The really incredible part of this story is that Go came from... Google.
That's really the thing with PHP isn't it? Getting something done as Quick and Dirty as with PHP is not easy to do with any other language when it comes to "the web"
One possibility is to make a language that compiles to PHP, like what TypeScript is for JavaScript, but not necessarily superset.
PHP already has a ton of well tested infrastructure to interact with web servers so you don't want to reimplement that again. And by compiling to PHP you get the same request model that PHP has which works great for quick and dirty web jobs. You can also leverage the performance improvements of PHP.
If you could hook that up to apache with a handler it would be great
compile to PHP language file extension -> Apache handler -> compile it to PHP -> Apache handler -> PHP Apache SAPI
Who thinks what feature was inspired from what language is irrelevant.
A language that tries to advance the state of programming is the only selling point worth noting. This is a toy language, which means it either adds to the noise or will disappear.
Thanks! For the negative comments, I'm proud to say that I don't care. I've had bosses even ask me what the point of this is when I've shared it. Some perhaps don't understand that you can do things for the sake of doing it.
Overall the most difficult things to understand were:
- How context-free grammars are parsed, and how they're defined. I'm still not an expert, but I can say that I can write a recursive parser by hand. I wrote my own JSON parser based on my understanding [0]
- Garbage collection. I think most GC's are based on the mark-sweep algorithm. Perhaps even Java's
most advanced algorithms are a version of mark-sweep. Mark-sweep is so simple, that it took me a _long_ time to understand it. Reference counting and mark-sweep go together.
You mean the sweep phase goes through and cleans out all the objects with zero reference counts?
I always thought the point of reference counting was to deallocate the object once the count goes to zero (which is why people complain it is slow as it can lead to cascading effects).
As to “most GC's are based on the mark-sweep algorithm” — I have a whole folder of papers on different GC algorithms, probably not the rabbit hole you want to go down if you have something you’re happy with. The minischeme interpreter I poke at every once in a while has a super simple GC that I have to resist messing with because it Just Works™ and I’d be chasing my tail for who knows how long getting another one working.
I thought that the mark-sweep isn't even necessary, if you don't have cycles. Reference counting can be a sufficient GC strategy but when cycles are introduced, I think that's the problem that mark-sweep solves.
That's awesome. Which papers do you find the most useful?
> Tracing and reference counting are uniformly viewed as being fun-
damentally different approaches to garbage collection that possess
very distinct performance properties. We have implemented high-
performance collectors of both types, and in the process observed
that the more we optimized them, the more similarly they behaved
— that they seem to share some deep structure.
> We present a formulation of the two algorithms that shows that
they are in fact duals of each other. Intuitively, the difference is that
tracing operates on live objects, or “matter”, while reference count-
ing operates on dead objects, or “anti-matter”. For every operation
performed by the tracing collector, there is a precisely correspond-
ing anti-operation performed by the reference counting collector.
> Using this framework, we show that all high-performance col-
lectors (for example, deferred reference counting and generational
collection) are in fact hybrids of tracing and reference counting.
We develop a uniform cost-model for the collectors to quantify the
trade-offs that result from choosing different hybridizations of trac-
ing and reference counting. This allows the correct scheme to be
selected based on system performance requirements and the ex-
pected properties of the target application.
Don't despair, HN is especially cruel when it comes to programming languages. I had a project make the front page here and the top comment was "I think you are working on the wrong thing", so I think these comments are are about what I would expect given the community here.
Almost sounds like the opposite of something like Nim, which is also Python inspired but removed the dynamic typing and kept the indentation.
I think I prefer using curly braces to indentation. I seem to remember reading that Nim strictly enforces spaces over tabs (rather than having it as a linter rule, or just asking you pick one consistently) which has kept me away from the language for some time, whereas you don't tend to get those hard rules with curly braces. Could be wrong on that, and would be happy to be corrected
Sorry to detract from the main thread though, looks really nice regardless
You only tend to find that when the style your being forced to use happens to align with your own style, or you don't use the language/tool and therefore aren't affected by it.
In my experience, a lot of programmers will shout from the rooftops about the importance of consistency until the agreed upon standard isn't their standard, at which point consistency is no longer the most important matter at stake.
Paired with a characters-per-line limit, 4-space indents forces you to better modularise your so that it doesn't nest too deep (which usually happens when your code is becoming too complex) so I guess that's the wisdom behind the convention.
> You only tend to find that when the style your being forced to use happens to align with your own style
My style is consistency. I'm happy to use any language that enforces that rather than leaving room for bikeshedding, even if the aesthetics aren't my personal favorite. Better than wasting time debating e.g. tabs vs. spaces.
Go enforces 1TBS over Allman style braces IIRC. I don't really care because I like 1TBS and also don't write Go but it did enstrange parts of the community.
Nim is mostly inspired by the Pascal/Modula/Oberon family, notably in its type system. The only thing it took from python (arguably) is the indentation-based block syntax.
Programming in Nim actually "feels" quite different from python to me, due to things like a much lighter OOP system (that is somewhat discouraged), the type system, and UFCS, though it "looks" like python at first glance.
This looks nice. As someone who is on-again/off-again on a side-project to design my own language[1], what would you say were the hardest, or most tedious, or least enjoyable[2] parts of the work leading up to this release.
[1] Compiled, though, not interpreted.
[2] Specifying what goes into the language, small snippets of code to show how certain features will look and behave, etc (basically language design) is very enjoyable, and I spend a lot of time doing (and redoing) this. Once I started on parsing into an AST I lose interest.
As with most things, the ancillary tasks are always the most annoying part of developing a language. Even if the language is just for yourself or a small group of people, you still need to build the tools around the language that make it usable and I find that to be the most tedious part and often the hardest part.
If you're getting hung up on parsing and what not, you might be more successful using a parser generator. People hate them, often for good reason, but they do allow you to iterate quickly at first.
I haven't used it personally, but if you plan on using LLVM I hear that is a nightmare to use. Probably would also fit in to the "hardest", "tedious" and "least enjoyable" category for you too.
> If you're getting hung up on parsing and what not, you might be more successful using a parser generator. People hate them, often for good reason, but they do allow you to iterate quickly at first.
I find using a parser combinator library or a PEG (https://en.wikipedia.org/wiki/Parsing_expression_grammar) is a better way to go. Usually expressing your grammar in these ways is not much more work than expressing it in an EBNF-esque style that a parser generator takes as input. The benefit is that you have a custom parser that is easier to modify and customize.
That is another great option, especially for getting started. This is something we have done at work to build our internal DSL. We used the wonderful Lark parsing library for Python. It allowed us to iterate very quickly and get the tool in the hands of the people that were intended to use it asap.
I don't think I would use a parsing lib to build a general purpose programming language though. At least not one that I intended to ship.
> > I don't think I would use a parsing lib to build a general purpose programming language though. At least not one that I intended to ship.
> Curious why not? Too big of a dependency?
Really very poor diagnostics. I've used a few, but for really nice helpful messages[1] you really need to build it yourself and handle some subset of the context when parsing the grammar.
--
[1] For example, maybe you want to issue errors of "'SomeVariable' not defined on line 53. Did you mean 'someVariable'?".
Or perhaps you want to issue the message "Unexpected end of input on line 570 - expected closing '}' to match opening '{' on line 515, column 22".
It gets especially annoying if the language provides meta-programming or compile-time logic - the parser generator, if it can even handle such a thing, spits out either an error for a line that is nowhere near the source of the error, or spits out pages and pages of a backtrace.
It is inevitable that you'd run into issues eventually that are due to the parsing library itself. Whether that be performance or otherwise. Sure, you can fix those problem in the lib yourself, but maybe you just can't for one reason or another. It is also possible that the lib is really good and has no problems, but your problem ends up being slightly different which makes it a pain to implement with the library that you choose.
When you are making a general purpose language that gets shipped to the masses, a core component of that thing you are making is the parsing. I'd say it is in your best interest to have complete control over how that works and be able to understand that well. That would mean putting in the work to make the parser yourself.
I don't just feel this way about building programming languages. I believe this is true for any kind of production level software that you write. It is important to maintain control and deep understanding of technologies that are core to your product. Building something from ready made components, while tempting, often ends badly.
The README says "Hint: Make sure String.ana is located in the directory of logger.ana. It's located in the lib directory." but I can't find a lib directory or String.ana anywhere in the repository?
Hey, so my apologies, but the README is inaccurate, unfortunately. Modules were removed in a commit, but they were working, they just weren't perfect. I plan to bring that commit back [0]
It’s really not that difficult to either switch layouts on the fly, or roll your own, so you can easily type the curly brackets.
Plenty of programming languages use the curly brackets, and English is the de facto language of tech.
And I’m not a native English speaker, and I have rolled my own keyboard layout that suits my particular needs on macOS (Ukelele), Windows (Microsoft Keyboard Layout Creator) and Ubuntu (forgot the name of the tool).
I understand your pain, but making a slightly custom layout is not that hard tbh.
And another tbh is that people who program does have an English layout, the only exception I know is 1с lang where all keywords are casting on Russian.
This is a great learning experience. There is a lack of people with the skill to reimagine how things are built so I’m sure this will pay off massively in future endeavours.
Reminds me of a C++ project I use to work on. The norm was to have generous function naming and not stick to the outdated C convention of short and cryptic names. The only exception was the function "anal", which was curiously shortened from "analyze".
I can honestly say that I never made this association, and it never crossed my mind once. Now that you mentioned it, I can see it. I just always say "analang" like golang
That's okay, I made a logo once that if you turned it to the side it was very bad, and I didn't notice for months. I like the other poster's suggestion of Annalang.
Curly braces and semicolons? Wait, that's actually C.
The README showcases some opcodes. Maybe they borrowed PHP's bytecode format or the VM design? If true, that would actually be a pretty neat thing to borrow, since PHP has made a lot of improvement in VM performance and memory management lately.
I like this. Has some nice features yet simple enough than I don't immediately dismiss it because I know I'll never have the time to properly wrap my head around it. Nice work.
New compiled languages like zig, jai, roc also focus in fast iteration. I remember a tweet by the Zig creators about it compiling and running a piece of code faster than python interpreted it.
Ultimately, while all valid programs must be well-typed, it's really hard to design and implement a (static) type system (and accompanying implementation) that's as expressive and ergonomic as a dynamic type system for expressing many well-typed programs that people want to write.
I'm all for static/strong typing and all, but I like being able to quickly apply hotfixes (or add logging to debug an issue) in production without having to wait for a full recompilation/rollout (which is undesirable when the system is down). For me, it's the only plus.
Speaking of fun little languages to create as a hobby. After having created several general-purpose languages like this one, I feel like most of such efforts (including mine) are, sadly, very similar to each other, with small variations. There's an urge to create another language for fun, but I wouldn't want to create another variation of the same thing yet again. So I wonder if there's some kind of catalogue of little hobby languages where authors are trying to explore novel, rare ideas, to get inspired by? Ideas like Rust's borrow checker, for example. The efforts I know about are mostly academic (for example, by Microsoft Research). So far my idee fixe lately has been to create a language which natively supports clean/hexagonal architecture/DDD (for example, clean layer separation can be enforced at compile-time, we use a special tool at work), but the lack of languages that explore these ideas makes me wonder why no one came up with it before, and why having monstruous frameworks with a lot of ceremony is the preferred way -- maybe there's already such a language, but it's too obscure to find it somewhere on the internet. A catalog would be useful.
The biggest issue with all these alternative languages, outside the yearly PhD work on compiler thesis across all universities and SIGPLAN papers, is making them into a product worthwhile adopting, the killer framework or platform that forces regular devs to actually adopt them.
That link is a little out of date. There's a spreadsheet floating around with more projects on it but I'm not exactly sure of the link.
It's a small but vibrant community. Our founding fathers would probably be Alan Kay and Bret Victor rather than Dennis Ritchie and Ken Thompson (not saying they founded our group but they are an endless font of inspiration for us).
We're trying all kinds of things in programming languages, and the main unspoken rule seems be be: no ALGOL derived languages allowed. Being ALGOL derived is what gives the "very similar to each other, with small variations" vibe that most programming languages have these days. In the PL field we iterated on improving imperative languages for the last 30-40 years, so a surefire way to end up with a radically different language is to build one in a different branch of the PL family tree.
131 comments
[ 3.7 ms ] story [ 193 ms ] threadI wonder what they took from c not counting the parts of c that literally everyone took
Because from the readme, it doesn’t look like this language brings anything to the table compared to Python/Node.
Its not that the project has to be ground breaking or anything, just be nice to know what we're looking at.
I get asked this question a lot. My goal for this project is not to convince you to use it. This new language does _nothing_ that you couldn't find in other languages today. This project won't take over the world, and many people ask me what the point of it is. It's purely a project stemmed from curiosity with absolutely no capitalistic motives. I did it based on my years of self-directed research studying many incredible programming languages, and this is what I have to show for my research.
My motivation for this was to learn how to build a programming language with a grammar, virtual machine, and garbage collector. It's a hobby project, not intended to be used for business.
> My motivation for this was to learn how to build a programming language with a grammar, virtual machine, and garbage collector.
Show HN FAQ:
> Show HN is for something you've made that other people can play with. HN users can try it out, give you feedback, and ask questions in the thread.
My guess is the author shared it for the learning opportunity.
Why not Annalang?
Maybe it wasn't intended, but having that screenshot as the tool's showcase sends a message to me.
The same problem bit me multiple times when pretty-printing nested data structures. There's often an arbitrary limit to the depth the printer recurse to and/or the number of elements that get displayed, with the rest hidden behind "..." or something similar. No matter what number you pick, sooner or later you're going to get a case where you miss a really interesting/important piece of information because it got hidden. And if you try to change the default, you're going to get a case where you miss important info because you couldn't be bothered to scroll that far up...
Anyway: you're right, this is bad, but also pretty common. Though in this particular case it's really bad, because most of the column width is taken by irrelevant data. Replacing `<function '` with λ would already help a lot.
At the programmer interface, sure. At the implementation level ("underlying"), all that abstraction is being turned into loops and jumps.
When I implemented Mindcode, I realized that “while” is the basic construct and that all enumerations and looping compiled down into goto.
Mindcode is a Ruby-like language for the Mindustry game. Mindustry has an assembly-like language with a visual editor in-game. Mindcode has a more traditional text-based flow.
Not necessarily; depending on what's going in in the loop, you can compile the code into parallel non-looping instructions that execute on multiple cores or threads. No loops needed.
In the general case, the statement is still true.
And anyway, even if it were a very specific case it's still an existence proof that disproves the assertions that "all that abstraction is being turned into loops and jumps." as one other poster put it. The replies here are speaking in very absolute terms ("you don’t have any choice", "loops and jumps cannot ever go away regardless of the higher level abstractions"), which are not true in an absolute sense.
The OP said:
> Do you mean for all imperative languages? Functional or declarative languages can do away with loops and jumps
And everyone here is answering them so far from the perspective of imperative languages. But depending on the program, it's not necessarily the general case in declarative languages, where we have much more freedom to compile things as we want, including without loops where they would be used in an imperative language.
Since this is a thread about language design and we're talking about alternative paradigms and how things get compiled to instructions, it's absolutely true that if our problem can be parallelized we don't have to loop at all. This is not a special case, but something that is generally applicable to many kinds of situations. Now that we're entering a world of potentially 1000s of cores available on consumer CPUs in the near future, what I'm saying is going to become the general case more and more.
In general, the iteration bounds aren't known and some kind of loop is required.
At least I'm not aware of any CPUs that are not imperative in operation.
> primitive and fundamental concepts do not go away even if things are abstracted by high level features in high-level languages.
Loops do not go away in fp. They are just hidden under layers of abstraction.
So they are both abstractions over goto, but i would say they are sibling abstractions not parent/child.
The loops are obviously there deep down the the language that they are implemented in but you never explicitly use them.
With go, they had to come up with a nickname for it (golang). So now the language has two names.
As a result, the typical "go <something>" and "golang <something>" search results will always be potentially imprecise, and partial (unless everybody in the world stops calling it "go" in favour of "golang".
The really incredible part of this story is that Go came from... Google.
Yeah. They leave SEO to other shops.
I think they did not even intend to have this language released in public at first.
The good ol Scunthorpe problem.
But it means you are partly right
PHP already has a ton of well tested infrastructure to interact with web servers so you don't want to reimplement that again. And by compiling to PHP you get the same request model that PHP has which works great for quick and dirty web jobs. You can also leverage the performance improvements of PHP.
If you could hook that up to apache with a handler it would be great
compile to PHP language file extension -> Apache handler -> compile it to PHP -> Apache handler -> PHP Apache SAPI
I am unfamiliar with PHP, wondering what benefits it has that might lead someone to choose it for a task today.
You can do stupid stuff like
<table> <?php foreach($array as $row){ ?> <tr><td><?php echo $row[0];?></td></tr> <?php } ?>
Meaning you can just inlay PHP in your raw HTML as you please, this example will reprint the <tr> and <td> for every key in $array
A language that tries to advance the state of programming is the only selling point worth noting. This is a toy language, which means it either adds to the noise or will disappear.
Overall the most difficult things to understand were:
- How context-free grammars are parsed, and how they're defined. I'm still not an expert, but I can say that I can write a recursive parser by hand. I wrote my own JSON parser based on my understanding [0]
- Garbage collection. I think most GC's are based on the mark-sweep algorithm. Perhaps even Java's most advanced algorithms are a version of mark-sweep. Mark-sweep is so simple, that it took me a _long_ time to understand it. Reference counting and mark-sweep go together.
[0] https://github.com/rmccullagh/libjsonparser
I love everything about this sentence
You mean the sweep phase goes through and cleans out all the objects with zero reference counts?
I always thought the point of reference counting was to deallocate the object once the count goes to zero (which is why people complain it is slow as it can lead to cascading effects).
As to “most GC's are based on the mark-sweep algorithm” — I have a whole folder of papers on different GC algorithms, probably not the rabbit hole you want to go down if you have something you’re happy with. The minischeme interpreter I poke at every once in a while has a super simple GC that I have to resist messing with because it Just Works™ and I’d be chasing my tail for who knows how long getting another one working.
That's awesome. Which papers do you find the most useful?
> Tracing and reference counting are uniformly viewed as being fun- damentally different approaches to garbage collection that possess very distinct performance properties. We have implemented high- performance collectors of both types, and in the process observed that the more we optimized them, the more similarly they behaved — that they seem to share some deep structure.
> We present a formulation of the two algorithms that shows that they are in fact duals of each other. Intuitively, the difference is that tracing operates on live objects, or “matter”, while reference count- ing operates on dead objects, or “anti-matter”. For every operation performed by the tracing collector, there is a precisely correspond- ing anti-operation performed by the reference counting collector.
> Using this framework, we show that all high-performance col- lectors (for example, deferred reference counting and generational collection) are in fact hybrids of tracing and reference counting. We develop a uniform cost-model for the collectors to quantify the trade-offs that result from choosing different hybridizations of trac- ing and reference counting. This allows the correct scheme to be selected based on system performance requirements and the ex- pected properties of the target application.
I think I prefer using curly braces to indentation. I seem to remember reading that Nim strictly enforces spaces over tabs (rather than having it as a linter rule, or just asking you pick one consistently) which has kept me away from the language for some time, whereas you don't tend to get those hard rules with curly braces. Could be wrong on that, and would be happy to be corrected
Sorry to detract from the main thread though, looks really nice regardless
In my experience, a lot of programmers will shout from the rooftops about the importance of consistency until the agreed upon standard isn't their standard, at which point consistency is no longer the most important matter at stake.
My style is consistency. I'm happy to use any language that enforces that rather than leaving room for bikeshedding, even if the aesthetics aren't my personal favorite. Better than wasting time debating e.g. tabs vs. spaces.
I have to deal with different coding styles at every work place, and it takes me all of a week to forget any objections I had to it when I started.
Braces are unnecessary.
Programming in Nim actually "feels" quite different from python to me, due to things like a much lighter OOP system (that is somewhat discouraged), the type system, and UFCS, though it "looks" like python at first glance.
[1] Compiled, though, not interpreted.
[2] Specifying what goes into the language, small snippets of code to show how certain features will look and behave, etc (basically language design) is very enjoyable, and I spend a lot of time doing (and redoing) this. Once I started on parsing into an AST I lose interest.
If you're getting hung up on parsing and what not, you might be more successful using a parser generator. People hate them, often for good reason, but they do allow you to iterate quickly at first.
I haven't used it personally, but if you plan on using LLVM I hear that is a nightmare to use. Probably would also fit in to the "hardest", "tedious" and "least enjoyable" category for you too.
I find using a parser combinator library or a PEG (https://en.wikipedia.org/wiki/Parsing_expression_grammar) is a better way to go. Usually expressing your grammar in these ways is not much more work than expressing it in an EBNF-esque style that a parser generator takes as input. The benefit is that you have a custom parser that is easier to modify and customize.
I don't think I would use a parsing lib to build a general purpose programming language though. At least not one that I intended to ship.
Curious why not? Too big of a dependency?
> Curious why not? Too big of a dependency?
Really very poor diagnostics. I've used a few, but for really nice helpful messages[1] you really need to build it yourself and handle some subset of the context when parsing the grammar.
--
[1] For example, maybe you want to issue errors of "'SomeVariable' not defined on line 53. Did you mean 'someVariable'?".
Or perhaps you want to issue the message "Unexpected end of input on line 570 - expected closing '}' to match opening '{' on line 515, column 22".
It gets especially annoying if the language provides meta-programming or compile-time logic - the parser generator, if it can even handle such a thing, spits out either an error for a line that is nowhere near the source of the error, or spits out pages and pages of a backtrace.
When you are making a general purpose language that gets shipped to the masses, a core component of that thing you are making is the parsing. I'd say it is in your best interest to have complete control over how that works and be able to understand that well. That would mean putting in the work to make the parser yourself.
I don't just feel this way about building programming languages. I believe this is true for any kind of production level software that you write. It is important to maintain control and deep understanding of technologies that are core to your product. Building something from ready made components, while tempting, often ends badly.
[0] https://github.com/analang/ana/commit/a2a62301388ae1843c60f2... [0] https://github.com/analang/ana/commit/a361c4498c0f44c4d28f4f...
Author could copy this title to the github description.
Plenty of programming languages use the curly brackets, and English is the de facto language of tech.
And I’m not a native English speaker, and I have rolled my own keyboard layout that suits my particular needs on macOS (Ukelele), Windows (Microsoft Keyboard Layout Creator) and Ubuntu (forgot the name of the tool).
And another tbh is that people who program does have an English layout, the only exception I know is 1с lang where all keywords are casting on Russian.
If you wish, could you add more details to your README file.
I intend to update the README soon.
Wish you all the best.
The README showcases some opcodes. Maybe they borrowed PHP's bytecode format or the VM design? If true, that would actually be a pretty neat thing to borrow, since PHP has made a lot of improvement in VM performance and memory management lately.
However, come to think of it, it's more close to Python and C then it is PHP.
Edit: here it is https://nitter.net/andy_kelley/status/1483677253682675713
Are you thinking of Roc or is this another language?
Dynamic typing didn't come to dominate for no reason.
But I agree it seems weird to make a new language without any distinguishing features.
https://github.com/dbohdan/embedded-scripting-languages
https://en.m.wikipedia.org/wiki/Cyclone_(programming_languag...
The biggest issue with all these alternative languages, outside the yearly PhD work on compiler thesis across all universities and SIGPLAN papers, is making them into a product worthwhile adopting, the killer framework or platform that forces regular devs to actually adopt them.
That link is a little out of date. There's a spreadsheet floating around with more projects on it but I'm not exactly sure of the link.
It's a small but vibrant community. Our founding fathers would probably be Alan Kay and Bret Victor rather than Dennis Ritchie and Ken Thompson (not saying they founded our group but they are an endless font of inspiration for us).
We're trying all kinds of things in programming languages, and the main unspoken rule seems be be: no ALGOL derived languages allowed. Being ALGOL derived is what gives the "very similar to each other, with small variations" vibe that most programming languages have these days. In the PL field we iterated on improving imperative languages for the last 30-40 years, so a surefire way to end up with a radically different language is to build one in a different branch of the PL family tree.
https://futureofcoding.org if it wasn't obvious what the link is to the main site.
Edit: here's the spreadsheet: https://docs.google.com/spreadsheets/d/12sTu7RT-s_QlAupY1v-3...