Introducing Owl
To say that writing your own programming language is a rewarding experience is about as understated as I can phrase it. I've been working on a little side project for the past month or so on something I've decided to call Owl. Owl is a dynamically typed, procedural, Algol-like language. It has syntax similar to pascal, and scoping rules in the same vein as C (no nested procedures).
My first iteration compiled to p-code and ran in a "traditional" stack machine type VM. I've recently decided to take a step back, and have re-implemented Owl as a tree walking interpreter while I stabilize both the syntax and the feature profile.
One effect of switching interpreter schemes is that development has sped up rapidly, and In doing so I recently passed what is to me, a significant milestone. Owl is now feature-rich enough to do non-trivial tasks beyond things like calculating Fibonacci numbers and factorials: shortly after implementing arrays (with bounds checking!) in the new interpreter, I was able to write a sorting routine to sort the array. And even though that sorting routine is a pretty much bubble sort, It was still really cool to do it in my own language.
Sorting an array with Owl
Being Algol-like in it's syntax, Owl is somewhat on the verbose side making use of the words begin and end instead of curly braces to delimit scope changes for example, but you quickly get used to it. Despite this, Owl is similar enough to other Algol descendants that swapping two elements in an array is instantly recognizable:
func swap(v: int, u: int) begin
let t: int := 0;
t := x[v];
x[v] := x[u];
x[u] := t;
ds := 1;
end
Declarations expect constants in Owl and not expressions, which is why you
see the variable 't' being initialized twice. When initializing the counter with a constant this isn't required, as you can see from showArr() below. This is one of those small quirks I plan to smooth out in the future, but they also gives Owl a bit of personality.
func showArr(n: int) begin {* display contents of an array *}
let k: int := 1;
while (k < n) begin
print x[k];
k := k + 1;
end;
end
The code to perform the actual sort is a standard bubble sort: check each element against it's neighbor, and if they are out of place swap them. When we reach the end of the array, if we didn't perform any swaps the array is sorted and can exit, otherwise reset the did-swap flag and perform the sort pass again.
func sortPass(m: int, n: int) begin
c := m;
d := c + 1;
while (d < n) begin
if (x[d] < x[c]) then
swap(c, d);
end;
c := c + 1;
d := c + 1;
end;
end
func sort(l: int) begin
ds := 0; {* did swap flag, once sortPass completes without setting to 1, were done. *}
sortPass(1, l); {* do bubble pass *}
if (ds = 0) then {* check did swap flag status *}
return 0; {* no swaps, were done *}
else
sort(l); {* did a swap, keep sorting *}
end;
end
And of course, what you've come to see! Did I mention that Owl has access to the systems random number generator?
i := 1;
while (i < 10) begin
x[i] := rand(50);
i := i + 1;
end;
sort(10);
showArr(10);
max@MaxGorenLaptop:~/GitHub/OwlInterpreter$ ./owlcli owlcode/bubblesort.owl
3
11
13
19
24
33
42
47
49
max@MaxGorenLaptop:~/GitHub/OwlInterpreter$
Pretty neat eh? Anyway, thats all I've got for today. Until the next time, Happy Hacking!
Oh, and if in the meantime you're curious about Owl, you can download the code for the interpreter and play! https://github.com/maxgoren/OwlInterpreter/
-
Generating P-Code by AST Traversal
-
Ternary Search Tries: String Specific Ordered Symbol Tables
-
Digital Search Trees
-
Lossless Compression Part III: Huffman Coding
-
Lossless Compression Part II: The LZ77 Algorithm
-
Lossless Compression Part I: Working with Bits in a Byte Oriented World
-
Bottom Up AVL Tree: The OG Self-Balancing Binary Search Tree
-
A Different Take on Merge Sort: Binary Search Trees?
-
Deleting Entries From Open-Address Hash tables
-
Transform any Binary Search Tree in to a Sorted Linked List
Leave A Comment