Showing posts with label golfrun. Show all posts
Showing posts with label golfrun. Show all posts

2014-02-22

Plans for Golfrun

The C Golfrun interpreter is stuck, as it was before. I think there's no reason to keep the idea of a full formalization of the language. I still want to rewrite it in C++11, but I don't want to find myself trying to inflate this or that feature of the language for the sake of it. Rather, I will use bits of C++11 when and if they fit; otherwise, plain C++, and even not too much C++ized i.e., it will be C++ for the STL, rather than for heavy Object Orientation; likely STL will be just a cozy replacement for the glib, and that'll be all.

In the meantime the language drifted and diverged from GolfScript in my mind. And from current Golfrun too! The changes I thought about were
  • no comments: code golfing can lack comments; and if you need them, a string that then you will drop from the stack can be used instead. There's a difference of course, since the string is digested at the lexical analyzer level while a comment is consumed by the parser and never results in a token. In contrast with a common good practice, the rule is: avoid comments! The change makes the symbol # available for other magic;
  • strings: use only "; strings without escape characters interpretation can be added through another syntax, like _"string". Another symbol, ', will be available;
  • case unsensitive symbols: case change can be used to separate symbols; e.g. thisIS has two tokens, THIS and IS. It could be useful to save some extra space.  A sequence like ThIs will produce 4 tokes: T, H, I, S.
  • maybe, rational numbers: a syntax like 0r13/3 could be used. A number like 0.123 would be written as 0r123/100, which has length 9 against 5. Cumbersome, and bad for code golfing in few strokes. Maybe I should accept the fact that a new symbol must be exploited for this; e.g. 0'123. No, I don't want to make it impossible to duplicate a number without adding extra space(s), e.g. 12.13++ must leave 37 on stack and not give a stack underflow instead. So maybe the dup must become ' and the dot must be back to its common meaning as part of syntax for numbers.
    • Rather the ' could be used as part of the syntax to introduce some kind of literals, e.g. '0.123 (where the dot is the decimal separator)
  • underscore can't be part of a symbol anymore, so hey_ and _hey will result both in two symbol tokens. But if followed by a number, it will be the unary minus, as in J; so you can write 5_5+ instead of 5 -5+ and the minus will be only a dyadic operator.
  • assignment syntax can't be used to assign to single character non-alphabetic symbols, e.g. {5}:* won't work. Instead, the syntax could be used to mean some sort of symbol modifier, i.e. interpreted as the token :*. The longer assignment syntax will be used (to be defined; it will be similar to the lookup system service) 
Other syntax changes were already made, in particular those allowing to feed the stack with complex numbers and to write the colon symbol (simply doubling it). Data types are or will be:
  • numbers
    • integers (arbitrary precision using the GNU Multiprecision arithmetic library)
    • complex integers, i.e. there's a real (integer) part and an imaginary (integer) part
    • rationals (complex or not), maybe
  • strings (of bytes; not C strings, so that they can contain zero bytes as well)
  • blocks, they are strings after all, but with a different syntax and can trigger different behaviour of operators
  • arrays (collection of eterogeneous objects)
  • hashmaps (keys are only strings; these strings can be the string representation of an object)
There will be 2 stacks: operands stack, and context stack. The context stack "contains" the operands stack and the symbol table. Currently, Golfrun can restore the original symbol table using a specific “system service”. This won't be needed anymore and the mechanisms of the context can be used instead. The context provides basically local variables capabilities and local stack capabilities.

Some extra built-ins will be kept, e.g.
  • dd (as 2dup in Forth); shorter synonym: D
  • sys (“system service”); single symbol ":" (written :: in the syntax) as synonym
  • stack (debug purpose mainly: dump the stack => stack associated with the topmost context)
  • sqrt (now it could return rational numbers approximating the result); shorter synonym: ST.
  • type (return the type of the object on the stack, without dropping it; shorter synonym: T
Others, added: e.g. 2swap (Forth) as SS, and rotation of more than 3 objects (@), as R.

A lot of symbols are now "free", and others need to have a defined behaviour with some kind of arguments. Coercion/implicit conversions need a clear, easy to remember rule.

An example of unclear behaviour is: [97 98]""+1/ will result in an array with two single character strings, "a" and "b". How do you go back? Something more elaborated as {(\;}%. This means that ( (or )) over a string will behave as if the string is an array of integers, except that the "head" (or "tail") is pushed as such, while the string remains a string. This is the same in GolfScript, where "ab") will result in two objects on stack, the string "a" and the integer 98. To get the "head" or the "tail" as single character, we need some extra work. In the eye of some operators, a string is an array of integers. Which is not wrong, but sometimes the information of the original interepretation is lost and coercion makes sense only if I am going to sum it with an integer. Something like Erlang $a could be desiderable (not using $  but something else instead).

Ok, I think it's time I start to code, without needing to have all this already planned in details, otherwise I won't start it again anymore.

2013-10-03

Github. A note

I had (and now I have again) a github account. My intention was to move Golfrun C++11 implementation there, but indeed I've never started it, nor I've finished plain C implementation, which is a mess. I had used only the gist, and there's a couple of articles here linking to gists. But they disappeared, I suppose since my account was “dormient”. Now I have created it again, but those gists are gone. I think I should rewrite them, but I am too lazy these days (months? years?). A lesson: figure if you can trust (free) clouds. I am joking, of course.

Edit

Indeed, gists are back, but now they think I am not a human… I think I'll be human again in 2014.

2012-11-03

Golfrun is not running (too fast or at all)

My tiny project Golfrun is stuck. There are several reasons: first, time. Ok, I am lying: I would have the time to, if only I would spend all my spare time on it. But of course I don't want to. Second, something that began as a "as fast as possible" C translation of "high level" Ruby powered interpreter, took its own path towards becoming an almost serious (though toy still) language. I suspect that the most horrorful part is the set functions implementation: naive, to say the least: I wanted them quick saying to myself the biggest and maybe most common lie (I will program it better later — I will fix it — I will enhance it... and so on). What I really wanted quickly done was indeed the whole thing, so that I could say ok there exists a full working interpreter for the official Golfrun language specification. Wait! I have not finished the specification either! Maybe there's another fact to learn: C is not the best language for fast "prototyping". C++ would have been better maybe but indeed the parent-cousin GolfScript teaches that languages like Ruby are good at that. (But they may fail in performance, which is the main reason I began GolfRun!)
Saying it differently: to me GolfRun has become already unmaintenable. So tiny, so dirty (not the worst anyway!), so wrong: it needs to be rewritten from scratch having now a clearer look of the goals. I had already the intent and the chosen language was C++11, yes C++11; anyway not for tough object orientation, which I don't appreciate when stretched too much. I like C and I would like to keep a C implementation of GolfRun, but I need to pause.
Furthermore the idea to write a serious (as possible) and formal-like specification of the language is cool (to me), but it erodes time changing a small project into a fake big one. So I will drop it and stick rather to a simple and maybe unexhaustive documentation.
It looks silly to apply metrics to a toy project but I have just downloaded pmccabe so I have tried a run and the uninterpreted results (with -vT options over .c files only) are:
  • Modified McCabe Cyclomatic Complexity: 1171
  • Traditional McCabe Cyclomatic Complexity: 1297
  • # Statements in function: 3485
  • # lines in function: 7872
 but indeed more interesting are the single function results. Reading here suggests that there are 14 functions with moderate risk, 14 functions with high risk, and 2 functions that are "the most complex and highly unstable method function". It fits my own perception :) (But take into account the fact that the number of functions, as counted by pmccabe, with less than 11 are 148 — are there 178 functions?...)

Now let me drift away using as a weak hook the simple "rewrite from scratch" mantra. If a project is becoming a bog, full of decaying boiling spaghetti code, growing without a guide and design (enforced by some good software engineering principles, rules, whatever) and becoming rather unmaintainable it could be a great idea to do it. It does not mean you have to throw away all the old code (unless it sucks totally): you can recycle it as well. But it exists what I would call business driven development: the code is not important, the code is not the product, so if "it works", let it shine — until the next unexpected bug shows up and then you have to blame the programmers, the lack of some good development paradigm and tests (but topsitters ignore or pretend to ignore what TDD is and that there are clues suggesting it's the time to move on and beyond well established past bad habits and enforce some good SE principles — I like very much "don't test your own software", which pairs well with TDD despite what you may think), the skills of the enchained programmers and everything else but the lack of a plan to bring the code in the new century and reduce the bugs likelihood. It worked... but the less you modify the code, the less old bugs manifest themselves means that the code has never worked for real (and what about a bug dancing around because some compiling option has changed?!). It means we deserved the "works on the test machine badge". It is still the programmer who did not rebel or left, who decided to bow to some kind of wrong logic (sometimes with the excuse "it's the customer's will"), who did not say "I won't add features until we fix it all")... it is such a programmer to be blamed; this is the sad truth. Though you can think, my reader, that if we wait to have a bugs-free product, we can wait forever before we can add new features; true if I were talking about bugs... indeed I am thinking about something more substantial: the whole software! No, almost joking now...
Nonetheless it's also a common human pattern to shift responsibilities away (but this is also the reason why rules and methodologies exist) so that in a specific environment  we can say or only think one or more of the following: I am not paid enough to worry about it (even if someone could point at you screaming "it's your fault!" and you can get fired for this not-so-correct-claim); it's not my fault (spaghetti code entanglements give strong unexpected coupling with the help of global variables, unitialized structs which by chance happen to be correctly zeroed for a while or worse before you added your code, bad "pattern" cloning and copy-pasting in order to keep the code looks like it used to look and avoid other developers screaming "oh why did you do it the hard way, we've never done it like that before" or similar claims); where's the black-on-white requirements?; I have tried to apply some good software engineering principle, but I am alone and it turned to be impossible (I won't explain why further), so I have warned you that the probability of bugs occurring despite the fact that programmers and testers did their job well is far higher than the minimum acceptable threshold; and so on... the list can be long.
I admit I have a bad habit: when I am developing something and I notice something that could be a bug, I fix it. (Could be? I wrote could be? A bug is, or a bug is not... this is a part of the problem, indeed, but I won't explain). People may think that it's ok, if it is a real bug, you have to fix it. Wrong. It must not be done (unless it is your bug!). You have to wait the bug to manifest and then, not before, be the hero fixing it quickly. This is a matter of balance. If you fix, say, 5 bugs you have not contributed to, bugs which never had the chance to do their show, then nobody will notice. If you add 1 bug that wins its run exhibiting its evil, then you are the one who added that bug (not the one that added that bug but removed 5 other someone else bugs). Thus, a bug that nobody noticed yet (and that he does not "own") is an asset for the developer, and should not be "spent" without earning publicly something. The are other interesting finding: half the doubled skilled persons could maintain the same code at the same total cost, making less frequent bugs by redesigning the software in order to reduce their probability — which makes the difference between "it works" (good) and "eureka it works!" (surprise, not good). But it means more unemployed persons and topsitters having less slaves to control; it seems like they exist metrics where quantity is more imporant (than quality) so that a topsitters managing 10 persons is more important than one managing 3 persons, if even their budget is (almost) the same. Fuck the topsitters: what about unemployed persons? In a good world they wouldn't be unemployed for so long, they would find a job their skills are suited for (needless to say, maybe not in the same industry). But things are a little bit more complicated here. There would be a lot to say about topsitters too. But it's better I stop.
Final wandering words to summarize it: it's not always only developer's fault but it's the developer to be blamed, thus it's always the developer's fault. Developers are weakly bound to their seats while topsitters are strongly bound to their seats, so developers can be replaced swiftly and more easily. Topsitters can hide their own faults, architectural deficiencies, the lack of good software engineering principles and leaders or guiding rules behind the developers faults.
By the way, ants colonies are wonderful.

(links about SE are chosen at random from a cheap google search, they are by no way reference links)