8 ms·
Show HN: Whack – A simply-designed compiled programming language
- wycliffb 8y agoJust pushed LLVM.dll to snapshot folder.
- wycliffb 8y agoWill appreciate comments on the implementation/design choices.
- TheDong 8y agoI think you'll get more comments if you include specific code samples. How would you implement the Fibonacci sequence in whack? How might one organize a simple game of hangman? If it's suitable for use as a tcp server/client, how about a "echo" client? Things like that can really show off the stdlib and the syntax choices. Relatively few people will read through the code, and even those that do will likely understand the code better if they start from "this is the syntax or idea that needs to be implemented" as expressed in example code. Documentation is also, obviously, more coherent to read than implementation code, and you don't seem to have any documentation explaining what features whack has (other than a note that it doesn't have a comprehensive type system).
- wycliffb 8y agoThere's a sample file main.w in the snapshot folder, there's also a grammar file at the source root.
- dan-robertson 8y agoIn that file I saw the line: r.amazing(); But that function is defined as taking a Bool. What is this call supposed to do? I’m also curious how you plan to implement match type. How would this work if you give it eg a char ? Will the compiler know what the type is and pick the right clause. I don’t really see a way to do it by inspecting the data at runtime so maybe the pointer would have to have runtime type information attached to it, but you would then need to transform that info when dereferencing the pointer as this info can’t live in memory next to the pointed-at objects if you want C compatibility. I also can’t really tell what match type is for from your example. Are you intending to have inheritance and then using match type as a kind of ad-hoc polymorphism (eg is my Animal a Dog or is it a Cat?), or some sort of weird template-like thing, or something else entirely? If you allow subtyping then does “func(Dog->Int)” successfully match something of type “func(Animal->Int)”?
- wycliffb 8y agoWill commence working on a doc to explain some design choices, and what some non-obvious code fragments do; will update here when I commit. There's no subtyping being done currently. The 'match type' construct matches the type of an expression at compile time. I should also add that some design choices may be reviewed before the first release.
- dan-robertson 8y agoSurely if match type is compile time and there is no subtyping then it is basically a no-op type assert. I.e. it’s like writing (e : t) in ML? Or is it supposed to allow for some kind of ad-hoc polymorphism like: func foo(x) string { match type(x) { char** : return “an array of strings” int : return “a number” default : return “not sure” } } And this gets transformed into something like: func foo(Type x_t, x_t x) string { match(x_t) { pointer_t(pointer_t(char_t)) : return ... ... } }
- wycliffb 8y agoInteresting suggestion! Will be sure to add that when I can.
- Myrth 8y agoAmazing job, thank you for sharing!
- SamReidHughes 8y agoI only looked for a few minutes, so first impressions: 1. Try the declaration syntax x Foo; instead of Foo x; I tried it before, you might like it. 2. I think the way you're defining the AST types is a crapload of work. You should have had a bunch of dumb structs, all in one file. Then you can see everything at once, and you aren't mixing AST representation with codegen logic. Sometimes that's a better way to do algebraic types in C or C++. 3. I don't know what "type Foo struct {...}" does but you'll save a lot of work if the type system only has names as types, nominative typing, without losing usability. 4. Personally I'd parse straight to the AST type you define and not use the mpc lib with its own AST implementation. I don't believe in parser combinator libraries, especially not in C. It's better to copy/paste those loops. Better than using a parser generator too. But since you have a parser already... not right now. Edit: 5. Avoid looking at Zig, Myrddin, etcetera, if you can. There are obviously paths that any C-like language tends to go down in the 21st century, and the world would probably be better if you rethought the problems from a blanket slate.
- wycliffb 8y agoCurrently following up on comments 1 and 3. Very good suggestions.
- exikyut 8y ago> Edit: 5. Avoid looking at Zig, Myrddin, etcetera, if you can. There are obviously paths that any C-like language tends to go down in the 21st century, and the world would probably be better if you rethought the problems from a blanket slate. I read the points above this one and cannot comment/disagree with them. However, I am very curious about (5). - What would you classify as "etcetera" here? (ie what other languages would you list) - What are the paths in question? - With said blanket slate, what other mindset may be useful to keep in mind? Thanks!
- SamReidHughes 8y agoBlanker slate, damn iPhone. More of a blank slate. I don't know, it's a general problem of balancing the originality you might get from not looking at other people's work, with what you miss out from not looking at it. "Etcetera" includes other low-level languages people've made. Like, I guess Go might even count. Honestly 5 is kind of stupid. No great reason not to ignore it. It's the sort of thing to do for 1 month, but not forever. By "paths" I mean different features that different languages have and how they do them. You could just copy how these languages try to improve the ergonomics around error handling, for example, or you could decide how you'd like to do it. Thinking from first principles it's likely you'll end up walking into exactly the same decision other languages make, only with a different choice of operator. But it's possible you'd improve matters. Other paths are questions like implicit conversions or how do explicit conversions happen. And what do you name the bitwise negation operator? Can you do pointer arithmetic? How do you handle pointers to array elements? Do you have a one-to-one mapping from indentifiers to indentificands?
- webkike 8y ago> Whack currently lacks a comprehensively designed type system. To me, this statement means: currently whack is not a properly designed programming language. Proofs are an important part of programming! This is the most important part.
- chrisseaton 8y agoLots of properly designed and practically useful languages have no comprehensive type system.
- kd0amg 8y agoIt is entirely possible to write proofs about untyped code.
- fuddle 8y agoIt would be a good idea to add some examples to the readme.
- wycliffb 8y agoWill remember to do so: will add an example for each language feature.
- otabdeveloper2 8y ago> Whack currently lacks a comprehensively designed type system. The type system is 90% of programming language design effort. This is like releasing a car without a 'comprehensively designed engine'.
- maxnoe 8y agoTo be fair, this is probably far from being "released"
- xixixao 8y agoI know that mentioning other language on a thread about A language is contentious, but if you haven’t played with Nim, I seriously recommend you check it out.
- lewisj489 8y agoShwacked
- nsstring96 8y agoThis is super cool, thanks for sharing! Are there any books or other resources that you found helpful in learning and implementing Whack? I’m dabbling a little bit with PLs and would love to hear your opinion.
- wycliffb 8y agoCheck: https://github.com/aalhour/awesome-compilers https://github.com/aalhour/awesome-compilers
- wycliffb 8y agoYou might find Types and programming languages - Benjamin C. Pierce to be particularly interesting. There's a GitHub repo with a list of materials, can't seem to find it. When I do, will remember to share!
- nsstring96 8y agoThank you! Looks very interesting. As for working with LLVM codegen libraries, would you recommend anything beyond the official docs? I found that most books for this sort of thing are based older APIs from a few versions ago.
- wycliffb 8y agoI haven't come across good material on the matter. If you do use C++ I do recommend you employ RAAI idiom in code generation for help with lexical scoping for your language.
- joshumax 8y agoInteresting project! I've written compiler frontends for both GCC and LLVM, and surprisingly found it easier to write one for GCC, despite LLVMs reputation on modularity. I'd love to hear the reasons why you chose LLVM for code generation over something else!
- thechao 8y agoIn my experience, LLVM has too much code motion for understaffed projects to seriously consider. When I’m developing small languages my goal is to reduce overall work or, barring that, keep the work constant & get some other benefit. While I always reach for c++ first, I’m under no delusion that it’s a fit language for describing easily portable, easily consumable, and stable API/ABI. For that work, C is the undisputed grand champion. As such, I generally just translate to C. With the vector intrinsics provided by Clang (or GCC), I can still target all the features I need.
- pppaul 8y agowould recommend looking into writing a grammar, have that generate your AST, then do some transformations on the AST to generate code. you will save a lot of time. I recently did that for a language that i made, via instaparse. the flexibility and speed i gained was very big. my language isn't Turing complete, but it has functions, lookup tables, and some pattern matching.
- wycliffb 8y ago> would recommend looking into writing a grammar, have that generate your AST, then do some transformations on the AST to generate code. you will save a lot of time. I had this thought, so I used a parser combinator (mpc) to generate the AST from the grammar and source file, then extract useful elements from the AST for codegen.
- rurban 8y agoWith mpc you can support macros, adding better macro definitions at compile-time, not just primitive cpp-style replacements. This would be definitely a game changer.
- devoply 8y agoI wanna see a language that is both dynamic and can be compiled. Runs on a VM and on bare metal. Something like C++, Java, and Python combined. It can definitely be done and would be an interesting exercise.
- frutiger 8y ago> that is both dynamic and can be compiled JavaScript is dynamic and compiled (as are many other dynamically-typed JIT languages). Did you mean dynamically typed and optionally statically typed? > Runs on a VM and on bare metal JavaScript is also runs on a VM and bare metal (e.g. V8's Ignition interpreter will interpret JavaScript, but TurboFan will compile it to machine code).
- devoply 8y agoYeah I guess that's true. And I guess you could use TypeScript if you don't like Javascript.