From Expressions to Bytecode
Previously, we had generated a set of semantically meaningful expressions from an arbitrary (but simple) block of code (shown at the start of the post before that). In this post, I’ll go into the process of converting the tree into an intermediate language that our interpreter can understand. Of course, before we can generate instructions in this format, we need to define the format.
Words’ bytecode format, creatively named ‘Letters’ is, as I have previously mentioned, a set of instructions that operate on a stack based virtual machine. I have chosen a stack machine because I think it’ll be easier (i.e., faster) to develop, and because there is a reasonable amount of work around in translating stack machines to register machines (normally during JIT compilation) in Mono, C#, Java, Dalvik, etc – so I think there’s scope there if I need to cross that bridge later.
That said, I anticipate issues with implementing the Letters VM immediately – the biggest of these is that the stack is heterogeneous (the top of stack could be an int, or an object reference, or a string, or any of the basic types), which requires that the generated IL is explicit with types. I said previously that I would be referencing a lot of the C# IL design, but this is where Letters and CIL diverge. Stack based code also tends to be quite verbose, making what appear to be quite trivial code compile into something unexpectedly large – this is something we’ll cover later.
The Journey Continues
In this post, I will go through some of the basics of how I have set up my compiler to convert the AST generated by Hime into a decorated expression tree used by the compiler’s semantic analysis, and finally into a series of simple binary opcodes to be executed by the Words virtual machine.
As I mentioned in the previous post, I’m still looking at a very early stage in the language development – just a series of simple expressions involving literals and local variables. The stage we are interested in is post AST generation – Hime has informed us that the page is grammatically valid. It’s not up to the compiler to see if it actually makes sense.
At the core of the compilation system is the expression tree – Hime’s AST is not particularly useful for us as it is (essentially) a series of named nodes. While it encodes structure, it lacks all the richness of meaning. The (abridged) grammar, at this stage, is this:
exp_name -> tkIdentifier; exp_literal -> exp_integer_literal | exp_real_literal | exp_string_literal | exp_boolean_literal; type -> builtin_type; exp_local_declaration -> type exp_name; exp_local -> exp_name; exp_lvalue -> exp_local | exp_local_declaration; exp_parenthesized -> '(' exp_rvalue ')'; exp_cast -> '(' type ')' exp_unary; exp_unary -> exp_literal | exp_name | exp_parenthesized | exp_cast; exp_multiply -> exp_multiplicative '*' exp_unary; exp_divide -> exp_multiplicative '/' exp_unary; exp_modulo -> exp_multiplicative '%' exp_unary; exp_multiplicative -> exp_unary | exp_multiply | exp_divide | exp_modulo; exp_binary_minus -> exp_additive '-' exp_multiplicative; exp_binary_plus -> exp_additive '+' exp_multiplicative; exp_additive -> exp_multiplicative | exp_binary_plus | exp_binary_minus; exp_rvalue -> exp_additive; exp_assignment -> exp_lvalue '=' exp_rvalue; statement -> (exp_local_declaration | exp_assignment) ';'; statement_block -> statement*;
I’ve omitted some bits we’ve already covered (literals and types), but this shows how operator precedence is encoded.
Words with Expressions
Welcome to part two of my adventures in the development of Words – this is another retrospective look at what I’ve done so far over the last week or so. I’m pretty sure I’ve subconsciously decided that blogging is ~basically~ documentation, so I can continue my development guilt-free! Today, we’re going to look at some of the simple stuff to do with built-in types, and the kind of simple operators that most people implement when they write languages (before they give up and use a proper one instead). Surprisingly, this was a lot more involved that I had expected, mainly because I wanted to come up with some kind of consistent rules (I don’t want to make another PHP-level catastrophe).
Firstly, I limited the scope – the grammar I intended to support in this initial phase was:
// Variable declarations (exp_local -> type exp_simple_name) int testInt; // Variable initializers (exp_assign -> exp_lvalue '=' exp_rvalue) float initializedValue = 10.0f; // Simple expressions (+, -, *, /, %) as well as parenthesized expressions int example = ((10 + 1) * 35) % 6; // Casting operators int truncated = (int)(7.0f / 5.0f);
At this point, the individual Words file (*.wds, known henceforth as a page*But of course!) is basically just a series of these statements, and frankly I’m getting a little ahead of myself because those assignments actually didn’t do anything and I was really just looking at the generated code to see if it made any sense, BUT I DIGRESS: because first, we need to talk about types.
This is the first of (hopefully) several posts about a scripting language I have been working on in my spare time. I’m going to keep these posts relatively short*It makes it more likely that I’ll write them. and with luck, they’ll be an interesting documentation of my progress.
An Introduction to Words
Words is the exciting new scripting language I am working on*The name has plenty of mileage, you’ll see!. I have been toying with the idea of writing one for a while – mainly because it’s something I’ve never done before and they’re just so useful – especially compared against hard coding everything. That said, there are some facets of the more commonly used scripting languages that I don’t like (perhaps because I am not a rather set in my ways C++ programmer), and if I’m going to go to the effort of making a new language, I’m going to make it appeal to me. With that said, here are the design goals:
- Words must be a compiled language – there should be no room for typos or errors where types are misused.
- The language syntax should be of the brace (C-style) family, rather than whitespace-delimited (like Python) or “begin”/”end”/whatever like Lua.
- The design should be similar to other managed languages, no pointers or direct memory allocation allowed (or, perhaps better, it shouldn’t be needed).
- It must support vector types and vector maths for games by default.
- The runtime should be easy to integrate into C++
The first point is a pet peeve of mine – and this is mostly due to my own carelessness, but I find it really hard to write a moderately sized (e.g.,) Python or Lua (things which I use semi-often) script without making a typo somewhere and not noticing it until it inevitably blows up*Usually just before a long running operation can output results. due to me making a retarded error like misspelling “print” as “pint” or something. The second point is purely personal preference and I’m not going to say that there is a right and a wrong way to do that.*Except, obviously, whitespace delimiting is a horrible idea because people just won’t stick with tabs, the Lord’s indentation of choice. The third point is really about usage – if you’re going to care about this sort of stuff, use C++, not a scripting language. Scripting languages should be friendly enough that it’s easy to get something working, the compromise of such a deal being some additional level of distance from “the metal.”
That said, let’s dive straight in and see what I’ve been up to!
Today, we’ll be looking at one of my favourite implements in the toolbox of programming – the spin lock. These have a bit of a bad reputation, as the term often refers to less cultured variants of the structure, but I’m here to tell you when, why and how to use them.
Multithreaded codebases will inevitably suffer from contention at some point – and traditionally, we turn to kernel systems to ensure that we serialize all the threads that are fighting over the resource. The main system used is that of a mutex or mutual-exclusion structure. These take the form of a “token” or object (generally called ‘the’ mutex for convenience) which can only be held by one thread at a time. When a second thread asks to hold the mutex, the operating system suspends it and will not reschedule the thread for execution until the mutex has been released. Mutexes, by their connection to the OS scheduling system, are owned and maintained by the underlying operating system, and can be used to build up many other useful structures.
Today, I was angry. I am in fact still angry – and the reason for this is a game that has been soft launched in Australia; EA’s iOS/Android title, “Heroes of Dragon Age.” This game is an abomination beyond measure, and while I realize that to many people I probably sound pretty ranty, let me just preface this with a warning: buckle up, because you haven’t seen anything yet.
How to Ruin Gaming
Predictably – especially for a phone game – Heroes of Dragon Age, or “HoDA” for idiocy, uses a freemium payment model. In freemium games, the upfront cost of the title is zero, which means a large number of people will download the game to try it – out of boredom, curiosity or sheer randomness. However, unlike demos, a freemium game will use cunning tactics to bleed the player dry of all their hard earned cash. It’s a classic bait and switch – the game will have been carefully designed to compromise the experience at every juncture, offering to handwave away irritations at the low price of a few dollars. “This is great,” the player is meant to think, “I can pay as much or as little as I want!” The issue is that it’s not like that – if you pick up a freemium game, it’s not gating content (like the shareware games from my youth), it’s deliberately funnelling you into paying by being as addictive, and generally irritating, as it can get away with. The weak minded player chooses to spend two dollars rather than being forced to wait 20 minutes for another fix of the game, quickly racking up much more than they expect.
I despise this model of games – but in many ways it was inevitable. The iOS app market was a race to the bottom, games that took years to make were sold at sub-$5 prices, and the entitled gamers who lived on the platform would still whinge about spending money. Freemium solves this issue, and additionally appeals to “casual players” (imbeciles) who would not want to spend money on the purchase of a game. So what I’m saying is, you brought it on yourself. But this is just the tip of the iceberg-shaped travesty that is this game.
Dragon Rage, More Like
HoDA is essentially like one of those collectible monster card game things that Asians and arch-nerds play; except unlike games of that mould, it adventurously removes all strategy, charm and decisions from the mix. You have a collection of heroes (represented as low poly models of ‘miniatures’) who “do ‘battle'” with enemy miniatures, in the sense that you get to watch them undergo a series of random and erratic “attacks” until one side is left without any dudes. It’s an appalling re-imagining of something that could work (squad based pokemon style combat) – dumbed down to the point where it may as well be a dice roll, something that would be more aesthetically and morally pleasing.
Why have they fucked it up so royally? Good question. I suspect it’s to cater to what they believe is their target audience – people who find tying their shoes to be an exercise in deep, tactical decision-making – and also to ensure that you spend your hard earned premium currency on “runes” which let you, for a fixed amount of time, give your heroes slightly better AIs or buffs to make the random outcomes tilt in your favour. The game also suffers from a weird faux-complexity – something the tutorial (which is about a million pages long) tries to inform you about. I won’t go in to any of the features at length – you can recycle outclassed creatures by getting a hero to “consume” them, and you can put people on the front or the back line, making them last slightly longer. Sometimes. None of this has any real impact on the gameplay. For starters, there would probably have to be some gameplay for that to happen.
What may surprise people is that the core part of the game – spending “money” to get new random characters – is actually fine with me. I buy Magic cards, after all – so the idea of paying something to get a random chance at a super rare item (hero) is not a problem. It all falls apart because the heroes are all functionally identical – they have a bunch of meaningless stats and do some kind of damage to one or more bad guys, making an “epic” creature just a “common” creature with more HP.
As would be expected with such a sloppy production, the UI is terrible – badly thought out, unpolished and glitchy (fucked up scrolling? Check. Hiding the health behind the character models? Great idea. How about totally random button placement? Check. Tiny hitboxes? Sure, why not). The writing, which exists in an alarming quantity (at font size negative one million) is ponderous drivel that has nothing to do with anything – during (ostensibly) a re-enactment (the game is “set” around replaying famous battles from Thedas’ history) of the corruption in the Golden City (an important event in DA lore), I inexplicably had to fight some zebra hyena slash fiction creatures. I’m pretty sure that wasn’t in the codex, so I am left with the probability that the “level” “design” may not be very sensitive to the “story”. To really rub it in, I tried to purchase a “guaranteed epic character” for $2, but instead it just stole my money and said I would receive it “soon” (I never did). The game also manages to run like arse, a feat which is particularly impressive given that it looks worse than Dragon Age 2 and I have the very latest iPhone available.
They also put in the usual freemium contrivances – you run out of “stamina” after six battles, and you can either wait 20 minutes for your next fight or spend some “gems” (purchasable from the IAP store) to continue playing. As in all other freemium games, it’s a reprehensible method to force (hopefully hooked) players to spend money, of course, in HoDA’s case, the chance of wanting to actually continue is slim to none, so it’s perhaps less offensive – instead it affords you a natural opportunity to put the phone down in disgust and scrub yourself with steel wool.
Barely Worth a Score
HoDA is a pathetic pounding at the bloated, decaying corpse that is the Dragon Age franchise. While Bioware rightly recognized that DA2 not only damaged their franchise but also their perceived ability at not producing shit games (DA3 may actually be good – although I’m not pre-ordering it), it seems that someone in EA didn’t get the memo, and tried to out do DA2’s sterling attempt at ruining an IP. I can’t find anything redeemable about this game at all, and I didn’t feel this angry about Simcity, which I actually paid real money to preorder. It’s as if the title was thrown together by a bunch of professional charlatans, chasing the freemium gravy train and not having a speck of pride or talent coming through in their product.
To me, it is especially egregious as I not only spend scary amounts of money on Magic cards but I also love Dragon Age – and, done right, this game could have been like crack cocaine to my tendencies. But it falls so far short of the mark that it causes me physical pain. I actually went in search of other opinions about this title, just because I could barely believe how such a half-baked, ill-conceived fucktastrophe was actually released, however all I found was this rambling puff piece from Eurogamer – the author was apparently too busy fellating the producer to ask critical questions like “why does this game look so terrible” and “where, when you get right down to it, is the game part?” So in conclusion, I wouldn’t exactly recommend it.
I think I need to go and have a lie down.
|Consists of pressing ‘fight’ and waiting.||0/10|
|The original work appears to be terrible, most of it is a low-res, shoddy copy of DA:O/DA2||0/10|
|Story and Writing|
|Despite having approximately as many words as The Odyssey, none of them are worth reading.||0/10|
|Sound and Music|
|I spent half an hour playing this, wondering when I would find that spark of redemption. It never came.||0/10|
|Full of bugs, glitches, terrible performance and visuals.||0/10|
An almost impossibly terrible game that I hope joins the long list of failed freemium titles.
As a walking stereotype, I fuel my gaming and coding habits by ingesting scary quantities of energy drinks – I realized I was a lost cause when, a few years ago, I needed to have a pre-sleep can before I could relax. Now, while Red Bull may not be my energy drink staple (I am a fan of Frucor’s V), sometimes I like to slum it (don’t we all) and I will find myself cracking open the old winged bull. A few weeks ago, something strange happened – a new Red Bull variant turned up overnight, Red Bull Zero.
This, in itself, is actually a little odd if you ask me – unlike Coke Zero (which tastes quite different to Diet Coke – the latter was supposedly meant to appeal to women in the 80s), Red Bull already had a sugarfree form which is a pretty reasonable analogue to the normal formula. I’m not against artificially sweetened energy drinks, especially as the flavour du jour for many brands can be fairly accurately described as “diabetes with a hint of pineapple” (V “Master Chief” flavour – ew – has nearly 70g of sugar in a big can), so I thought I’d give it a shot. In the interests of science, I bought a can of the “normal” sugarfree kind as well, to produce an empirically accurate verdict.*
Pour, Smell and Colour
Both Red Bull Zero and Red Bull Sugarfree have a sickly “tropical” flavour that fills the room as soon as you open the can. For years, I didn’t really isolate what it actually tastes like, until I had some Red Bull sorbet (yes, I really do have a lot of energy drinks), which was very convincingly pineapple flavour. Of course that’s not all that it tastes of, but beyond that, it’s mostly unidentifiable noise and vague berry flavour. Anyway, they smell identical – or at least, that’s what I initially thought. Once we poured them out, it was pretty clear that our initial assessment was wrong, Red Bull Zero is much, much syrupier, while Red Bull Sugarfree has a tartness to it that balances it out. Also, while the liquids were exactly the same shade of Energy Drink Yellow (why are they all this colour?), Red Bull Zero is noticeably less fizzy.
Red Bull tastes just like it smells, which means that Zero had a cloying sweetness and a slightly flat sensation while Sugarfree was much more refreshing, washing away the taste of artificial “fruit” flavour with extra fizz and more unidentifiable sourness. Strangely, Red Bull Zero was also noticeably thicker than Sugarfree. I mean, it wasn’t like leek and potato soup or something like that, but, while Sugarfree is about as thick as soda water, Zero was practically jelly in comparison**.
After chomping through the Zero (with a knife and fork) and washing it down with the rest of its cousin, I went to the back of the can to check the nutrition info. A couple of things stood out – first, Zero has three artificial sweeteners: aspartame (nutrasweet), sucralose (splenda) and acesulfame potassium (“Ace-K” in the food industry), while Sugarfree has only the latter two. It’s typical for artificially sweetened drinks to mix sweeteners, by doing so, the manufacturers are able to mask each components’ unpleasant bitter taste (which will happen at some point). Aspartame and Ace-K are the common mix, while sucralose is generally viewed as a better sugar analogue (it is chemically similar to sugar, only with some hydroxy groups replaced by chlorine) – but is much less frequently used (I assume due to cost, as it is under patent). What is atypical is seeing three different forms in there, and I suspect that adds to the mushy, oversweet flavour (and may also be part of the thickening effect). They also removed a significant amount of sodium citrate and all magnesium carbonate, both of which were acting as a buffer to the citric acid and carboxylic acids, which would explain both the lack of sourness and carbonation, respectively. Also removed is something called glucuronolactone, which was added to energy drinks to, well, how about I quote the Red Bull Malaysia website:
Detoxifying Function: It helps to eliminate waste substances from the body which are produced within the body (endogenous) or which are taken up from the environment (exogenous). Waste substances / toxins are bound by glucuronolactone, thereby made water-soluble so they can be easily excreted via the kidneys.
– A professional liar
Yes, tell me more about this mystical “detoxifying” chemical! Does it prevent government mind control through fluoridated water (exogenous) as well?! Actually looking at my review of Wicked, it looks like this damn chemical keeps cropping up. I find it amusing that they’ve quietly dropped it from the Zero formula though – while they may be aiming to ~*toxify*~ everyone, it’s probably just fallen out of favour. I guess it’s all acai berries or something equally tenuous now.
Red Bull Zero is a pathetic cash in on the “zero” drink craze, which is surprising since I would’ve thought the Coca-Cola company would’ve sued the hell out of anyone who tried that. They have reformulated the product for the worse and if you disagree it is because you are wrong and not a true energy drink connoisseur like myself. Beyond that, the other parts are the same – it’s the same caffeine content (moderate), the same sugar content (zero), and approximately just a refresh of the older product. At the end of the day, I actually disliked Zero quite a lot – not because it’s bad per se (lord knows there are enough energy drinks that deserve that title), but because it was unnecessarily worse, as if they were just giving the finger to everyone out of spite. Typical.
* not empirical
** by that, I mean ‘about as thick as apple juice’
Cast your mind back to 1997 (if you weren’t alive back then, get off my lawn you pesky kids); Quake was ushering a new dawn of graphics (the much vaunted “origami in brown” look), and the last generation of 2.5D games were being released – one of which you may have heard of: Duke Nukem 3D. While Duke was a great game (which went on a sordid journey of its own), in the year that followed its release, 3D Realms didn’t sit on its laurels; they reskinned and rebalanced the game into a pastiche of Asian kung-fu movie stylings. They, in fact, made Shadow Warrior, essentially a Duke 3D Total Conversion with vastly more casual racism and a wafer thin plot. It was also a great game (and is now available for free on Steam!).
Now, 16 years later, Shadow Warrior is back – re-imagined, re-charged and… uh… re-updated by independent polish studio Flying Wild Hog (who previously brought us Hard Reset). Is this another cash in on nostalgia, or something more?
Recently, I entered the market for a new set of earbuds – I had just got a new phone (an iPhone 5S), and my prior set, while electrically sound, had suffered an unfortunate incident which had bent the connector. I had obviously received some of the magical apple earpods with my phone, but I’m afraid I was skeptical. Previous Apple earbuds leaked so much sound that I had started to suspect it was a covert marketing technique to promote iTunes (although obviously that would require the listener to pick something other than, e.g., Enrique Iglesias), but these were a pretty big departure.
I quickly ruled using them out (although the sound quality is better, less like a mosquito in a jar) because they feel like what I can only assume is akin to a spaceship trying to dock with your outer ear. It also doesn’t help that the USS Earbud D is made entirely of a futuristic frictionless plastic previously unknown to man, allowing it to successfully juxtapose a high risk of falling out and the intimate sensation of a speculum being rammed into your head.
Clearly, I needed to look elsewhere.
(This is a continuation from my post about return value optimization)
I thought it would be good to dig a little deeper into RVO and argument passing, mainly for my own curiosity’s sake. This time, we’re going to go down the rabbit hole – how are return values actually returned, and what happens when we return one of the arguments from our function? Let’s start, again, with RVO.
RVO Setup and Mechanism
Imagine your program’s stack – you have a bunch of locals in the frame you’re in, one of them is where you want to place the return value of a function call. To set up the call, you have to push the arguments of the function (from back to front), but crucially, the compiler inserts one extra argument – a hidden parameter that is the pointer to where you want the return to go.