Hi, I'm Christopher Chase; welcome to my website!

I'm a software engineer with a decade's worth of professional experience across the Health, Supply Chain, AdTech, Energy/IoT devices, Food & Beverage, and Consulting industries.

On this site you'll find posts about various projects or interests I have.


This site itself is a single page HTML file that uses a small amount of Javascript to provide some convenience for both me as the author and you as the reader. Directly below this, you'll find some tools to help you better navigate the various posts.

Designing a new website

Posted on

I last went through a website redesign back in December 2015. At the time, I had just heard about Asciidoctor, and I was still heavily playing around with the Perl language.

To add a new page to my site, I'd type it up in Asciidoctor, use some magical includes to get the common page header added, and then recompile the whole site using a Perl script. At the time, I thought this was really cool, but after 6 years and rarely (i.e. never) adding new content, my custom tooling became a hinderance: after years of not using it, I had forgotten how everything worked.

For my new site I knew that at the end of the day I wanted simplicity above all else:

With those design considerations in mind and a few hours of work, I believe I've come up with a solution.

For content creation, the following pattern is used.

By following the pattern outlined above, I was then able to use Javascript to consistently enhance blog-style posts:

I'm happy with the results so far. As I mentioned above, this entire site is a single page including all styles and Javascript, feel free to copy it and make it your own. (If you do, let me know so I can check out your site!)

A Simple Presentation DSL in Tcl

Posted on

Background

As I’ve written previously, one of Tcl’s greatest strengths is that it allows for the programmer to define new, first-class constructs in the language. In this post, I’d like to touch upon another one of its strengths: the ability to quickly create Domain Specific Languages.

Earlier today, I was watching a presentation given by Richard Hipp for the Tcl / Sqlite conference in 2020. In his presentation, he gave the link to his slides. They were just simple HTML pages that linked to one another.

Recently, I’ve been thinking more and more about Domain Specific Languages, so I figured I’d take a stab at making a DSL that generated HTML pages from "presentation files".

First, I started by simply writing a presentation in my theoretical DSL, not thinking too hard about the format. My goal was to write using an intuitive language and worry about the implementation later on.

Example presentation file

presentation-start

  slide
    title "A Simple Presentation DSL in Tcl"
    - "Presented by Christopher Chase."
    - "October 2021"

  slide
    title "Tcl"
    - "Tcl is a dynamic lanugage...."

  slide
    title "Third page"
    - "Bullet 1"
    - "Bullet 2"

presentation-end

About 30 minutes later (it’d take shorter if I was using Tcl every day, but it’s been a while!), I had a working implementation.

Implementation

array set presentation {}

proc presentation-start {} {
        global presentation

        unset presentation
        array set presentation {}
        set presentation(started) 1
        set presentation(slideCount) 0
}

proc presentation-end {} {
        global presentation

        # Loop through each of the slides and generate output (e.g. HTML)

        set currSlide 1

        while {$currSlide <= $presentation(slideCount) } {

                set isFirst [expr $currSlide == 1]
                set hasMore [expr $currSlide <  $presentation(slideCount)]
                set isLast  [expr $currSlide == $presentation(slideCount)]


                # If we're on the first slide, use the title as the directory name
                if {$isFirst} {
                        set dirName "$presentation(slide,$currSlide,title)"
                        file mkdir $dirName
                        cd $dirName
                }

                set fh [open $currSlide.html w+]

                puts $fh "<h1>$presentation(slide,$currSlide,title)</h1>"

                # Loop through each bullet on this slide
                set currBullet 1
                while {$currBullet <= $presentation(slide,$currSlide,bulletCount)} {
                        puts $fh "<p>$presentation(slide,$currSlide,$currBullet,text)</p>"
                        incr currBullet
                }

                if {$isFirst} {
                        # If currSlide is 1, we only link to next slide.
                        puts $fh "<a href='[expr $currSlide + 1].html'>Next</a>"
                } elseif {$hasMore} {
                        # If 1 < currSlide < slideCount, we link to prev and next
                        puts $fh "<a href='[expr $currSlide - 1].html'>Prev</a>"
                        puts $fh "<a href='[expr $currSlide + 1].html'>Next</a>"
                } elseif {$isLast} {
                        # If currSlide = slideCount, we link only to prev
                        puts $fh "<a href='[expr $currSlide - 1].html'>Prev</a>"
                }

                flush $fh
                close $fh
                incr currSlide
        }

}

proc slide {} {
        global presentation
        set sNum [incr presentation(slideCount)]
        set  presentation(slide,$sNum,bulletCount) 0
}

proc title {t} {
        global presentation

        set sNum $presentation(slideCount)
        set presentation(slide,$sNum,title) $t
}

proc - {t} {
        global presentation
        set sNum $presentation(slideCount)
        set bNum [incr presentation(slide,$sNum,bulletCount)]
        set presentation(slide,$sNum,$bNum,text) $t
}

The above code, less than 100 lines, reads a presentation file, and for each presentation, creates a new directory and then for each slide of the presentation, creates a new HTML file that links to the previous or next slide (depending on what page is being rendered.)

Defining until in Tcl

Posted on

Background

One of Tcl’s greatest strengths is the ability for the programmer to seamlessly create new control structures. In this example, we will define a new control structure called until. Until takes two parameters: the first is a test condidtion and the second is a script to run while the condition is not true. For example, if we wished to print all numbers from 1 to 10, we could write the following:

until {$i == 10} {puts $i; incr i 1}

This of course assumes that the variable i has already been initialized to some number.

Implementation

The first iteration and simplest form of our control structure, in pseudo-code, is as follows:

(1) Take the given test condition and run it in the caller’s scope.

(2) If the test is untrue

	(3) Take the given script and run it in the caller’s scope

	(4) Return to #1
				

Our first attempt at the code:

proc until {test body} {
	# We run the test in the caller’s scope, but check its return value in this scope
	if { ! [uplevel 1 $test] } {
		uplevel 1 $body
	}
}
				

Testing our procedure gives the following output:

set i 1
until {expr {$i == 10}} {puts $i; incr i 1}
> 1
> 2
		

We get two values back. The first, "1" is from our body-script’s put statement. The second, "2" is the return value of the incr command. Now that we’re sure our until control structure’s process flow works for a single iteration, we’ll modify it to run in a loop-like fasion. We do this by simply replacing the inner if-statement with the built in while command:

proc until {test body} {
	# We run the test in the caller’s scope, but check its return value in this scope
	while { ! [uplevel 1 $test] } {
		uplevel 1 $body
	}
}
			  

Again, we test:

set i 1
until {expr {$i == 10}} {puts $i; incr i 1}
> 1
> 2
> 3
> 4
> 5
> 6
> 7
> 8
> 9
			  

We have one additional step which is to clean up the call signature to until:

until {expr {$i == 10}} {puts $i; incr i 1}
			  

will become:

until {$i == 10} {puts $i; incr i 1}
			  

To make this change, we move the call to expr from the test expression into our procedure:

proc until {test body} {
	# We run the test in the caller’s scope, but check its return value in this scope
	while { ! [uplevel 1 {expr $test}] } {
		uplevel 1 $body
	}
}
			  

Calling our procedure, we get the following:

until {$i == 10} {puts $i; incr i 1}
				> can't read "test": no such variable

The reason for this is because the uplevel call in our while loop runs the literal form {expr $test} instead of the expanded form {expr {$i == 10}}. This is due to the use of curly-braces.

If we replace the braces with quotes instead:

proc until {test body} {
	# We run the test in the caller’s scope, but check its return value in this scope
	while { ! [uplevel 1 “expr $test”] } {
		uplevel 1 $body
	}
}	
				

We get another error:

until {$i == 10} {puts $i; incr i 1}
>invalid command name "“{expr"
				

The solution is actually much simpler than using braces or quotes. Uplevel concatenates all arguments together into a single list, and then performs its operation. That means we can do the following:

proc until {test body} {
	# We run the test in the caller’s scope, but check its return value in this scope
	while { ! [uplevel 1 expr $test] } {
		uplevel 1 $body
	}
}
				

Making an LED light writer

Posted on

Back in October, a friend of mine sent me a link to a reddit post where the user austron was showing off an LED light writer he had built. I thought it would be fun to recreate this project using an Arduino.

The first step was to wire up some LEDs on a breadboard and get them connected to the Arduino. I forget exactly why I chose to use 8 LEDs, but it seemed like a good number at the time. As I show later, it turned out to be a good choice. Below is a picture of the breadboard and Arduino. In case it’s not clear what’s going on, take a look at the accompanying schematic.

There’s nothing special about the digital pins I used. If you wish to create this project yourself using the code I provide, you’ll need to use 8 pins that are sequential.

Since the light writer consists of a single column of eight rows, each character that will be displayed needs to be sliced up. Below are two of the many ways in which the letter C can be split up. I chose to go with the one on the left. (Red squares represent lit LEDs, and white squares are unlit LEDs.)

After splitting letters up, they can be easily represented in the Arduino sketch. During the fist iteration of my code, I did everything manually:

It’s a pain to have to write out all that code for a simple message. And what if I wanted to display a different message? I would need to copy and paste and rearrange, and end up with a big mess. Making a function for each character would eliminate some of this mess:

If I had done this for every character, I could display the word “hello” by typing:

h(); e(); l(); l(); o();

Being able to quickly call a single function is convenient, but writing out each column of each letter like I did for the C is not. If you go back and count, you’ll notice that I had to use digitalWrite() 18 times just to represent the letter C. If I had continued to do this with every letter, that would have been a lot of code!

Instead of wasting time typing that all out, I began to think of a compact way in which I could represent an entire column at once. A byte seemed to be perfect. It holds 8 bits, and each bit represents an on-off state. I had 8 LEDs, and each LED is either on or off. Now, Instead of a single line representing a single LED state, it could represent an entire column’s state! The picture below helps visualize how the letter is represented using bytes:

I created the function lightUp which takes one of these bytes and turns on the corresponding LEDs. As I mentioned earlier, it doesn’t matter what digital pins are used, so long as they’re sequential. The loop in in the lightUp function is the reason for this.

After converting entire columns to bytes and creating the lightUp function, the letter C could now be represented by this code:

5 lines instead of 18. Not bad! This could be made even more compact by having the lightUp function work on an array of bytes.

To further reduce the amount of code, I decided to store the message as a string. A loop could then be used to iterate over each character in the string, and that letter’s corresponding function called:

After adjusting the time delays between individual characters and words, I was able to come up with some decent results:

Here’s a link to the full Arduino sketch file: https://gist.github.com/83156afded367c106bb7

Return to top