The earliest memory I have of ‘programming’ is in the early/mid 90s when my father brought home a computer from work. We could play games on it … so of course I took the spreadsheet program he used (LOTUS 123, did I date myself with that?) and tried to modify it to print out a helpful message for him. It … halfway worked? At least I could undo it so he could get back to work…

After that, I picked up programming for real in QBASIC (I still have a few of those programs lying around), got my own (junky) Linux desktop from my cousin, tried to learn VBasic (without a Windows machine), and eventually made it to high school… In college, I studied computer science and mathematics, mostly programming in Java/.NET, although with a bit of everything in the mix. A few of my oldest programming posts on this blog are from that time.

After that, on to grad school! Originally, I was going to study computational linguistics, but that fell through. Then programming languages (the school’s specialty). And finally I ended up studying censorship and computer security. That’s about where I am today!

But really, I still have a habit of doing a little bit of everything. Whatever seems interesting at the time!

# Lunar Arithmetic in Rust

I’ve been playing with various languages / language design a lot recently (inspired by my Runelang series). As I tweak and change what I’d like to implement in a language… I kept finding myself coming back to more or less exactly how Rust looks (albeit without the borrowing). So… that seems like a pretty good reason to start picking up some Rust. In another thread of thought, I stumbled upon two OEIS (on-line encyclopedia of integer sequences) sequences: A087061: Array T(n,k) = lunar sum n+k (n >= 0, k >= 0) read by antidiagonals and A087062: Array T(n,k) = lunar product n*k (n >= 1, k >= 1) read by antidiagonals.

# Runelang: A Summoning Circle Generator

Last time we had Runelang: A Bind Rune Generator. This time, let’s make ‘summoning circles’. Basically, we want to make a circle with stars and other circles inscribed and around the borders with various ‘mystic’ text in the mix. Something like this:

• generate_summoning_circle
• random chance of boder
• random chance of one or more inscribed stars
• random chance of recurring on the border (calling generate_summoning_circle again)
• random chance of recurring in the middle

# Runelang: A Bind Rune Generator

Continuing with my Runelang in the Browser series, I had the idea to automatically generate runes. So basically reversing the parsing step, rather than to take what I’ve written and make it look good, to write something that Runelang can parse–and still look good.

In a nutshell, I want to write a series of functions that can recursively call one another to render runes:

• generate_bind_rune
• n times generate_bind_rune_arm
• m times generate bars, circles, and other decrations
• add a fork at the end

# Runelang: Evaluation

As they say, life is what happens when you’re making other plans. But I’m back, so let’s talk some more about Runelang. In the interest of not dragging on months without finishing, we’re going to go ahead and push through the rest of the project. Onward!

# Runelang: The Parser (Part 2: Expressions)

Earlier this week, we started parsing, getting through groups, nodes, params, and lists. A pretty good start, but it also leaves out two very powerful things (expressions and defines), one of which we absolutely do need to start actually evaluating things: expressions. Since we use them in every param, we pretty much need to know how to parse them, so let’s do it!

# Runelang: The Parser (Part 1)

I’m still here! And less sick now.

Last time(s), we described and lexed) Runelang! This time around, let’s take the lexed tokens and go one step further and parse them!

So, how do we go about this? With a recursive descent parser!

• Start with a list/stream of tokens
• Using the first k (in a LL(k) parser) elements of the list, identify which sort of object we are parsing (a group / identifier / literal / expression / etc)
• Call a parsing function for that object type (parseGroup etc) that will:
• Recursively parse the given object type (this may in turn call more parse functions)
• Advance the token stream ‘consuming’ any tokens used in this group so the new ‘first’ element is the next object

# Runelang: The Lexer

Let’s LEX!

So this is actually one of the easier parts of a programming language. In this case, we need to turn the raw text of a program into a sequence of tokens / lexemes that will be easier to parse. In this case, we want to:

• Remove all whitespace and comments
• Store the row and column with the token to make debugging easier

So let’s do it!

# Runelang: Language Specification

Previously, I wrote a post about making a DSL in Ruby that could render magic circles/runes. It worked pretty well. I could turn things like this:

rune do
scale 0.9 do
circle
polygon 7
star 14, 3
star 7, 2
children 7, scale: 1/8r, offset: 1 do |i|
circle
invert do
text (0x2641 + i).chr Encoding::UTF_8
end
end
end
scale 0.15 do
translate x: -2 do circle; moon 0.45 end
circle
translate x: 2 do circle; moon 0.55 end
end
end


Into this:

But… I decided to completely rewrite it. Now it’s an entirely separate language:

# Go is faster than Python? (an example parsing huge JSON logs)

Recently at work I came across a problem where I had to go through a year’s worth of logs and corelate two different fields across all of our requests. On the good side, we have the logs stored as JSON objects (archived from Datadog which collects them). On the down side… it’s kind of a huge amount of data. Not as much as I’ve dealt with at previous jobs/in some academic problems, but we’re still talking on the order of terabytes.

On one hand, write up a quick Python script, fire and forget. It takes maybe ten minutes to write the code and (for this specific example) half an hour to run it on the specific cloud instance the logs lived on. So we’ll start with that. But then I got thinking… Python is supposed to be super slow right? Can I do better?

(Note: This problem is mostly disk bound. So Python actually for the most part does just fine.)