Streak Club is a place for hosting and participating in creative streaks.
I've got the itch to make a Go library. Without saying too much about it (in case I never release it) it could at some point be part of a web framework.
I'm not going to attempt every day, but I'll try to post here a bit again. I've more-or-less been lazy about submitting here. In any case, maybe this will motivate others to remember to submit again.
Mostly I've worked on GoForth the last couple of months. It's been pretty fun hitting 100% test coverage and benchmarking most implemented words. As an example:
BenchmarkCoreWordsStackSwapCodeWord-2 2000000 638 ns/op BenchmarkCoreWordsStackSwapFastCodeWord-2 5000000 339 ns/op BenchmarkCoreWordsStackRotCodeWord-2 2000000 837 ns/op BenchmarkCoreWordsStackRotFastCodeWord-2 5000000 270 ns/op
This shows a stack swap time performing 1.8x as fast and a stack rotation performing 3.1x as fast. This one speedup was taken across any operation that was popping from the stack and then pushing a result. In most cases, an item is popped if needed, and then the top item is changed in place (or in the case of unary operators, changed in place without any push/pop.)
I also now have a basic REPL. It was surprisingly short:
package main import ( "fmt" "forth" ) func main() { reader := make(chan rune) quit := make(chan bool) f := forth.NewForth() f.SetStdInOut() f.Reader(reader, quit) fmt.Println("Welcome to an example REPL.\nType die and press enter to exit") var s string for { fmt.Scan(&s) // Just a simple break out of the repl if s == "die" { break } for _, v := range s { reader <- v } reader <- ' ' } }
This will read from input, execute any words in the dictionary, and exit when you type " die" (without quotes and the leading space) and press enter.
Next up will likely be things like branching words and figuring out a good method for doing that.
Took another break mostly out of lack of time, other obligations, etc. I got back into it a bit tonight when I realized I hadn't updated Docker in a very long time (as in, I was on version 0.4.6 circa June 22, 2013) on my desktop at home. Upon updating that, also built the docker client for the BeagleBone Black.Unfortunately (and rather expectedly), the daemon wouldn't build.
After playing around with that a bit, I started prototyping a Forth implementation in Go. I got as far as defining a couple structures implementing a common word header (name & flags mostly.) They also satisfy a common interface which includes a codeword function. The linked version iterates through the functions executing them, while the func struct runs a single function defined in the structure. This seems like a pretty straight forward way to implement this, but I'll likely play around with other methods out of curiosity.
Needed to take a bit of a break after the 33 day streak. Spent a bit of time looking at the Forth word structure. Figured out .int was giving a 32 bit int instead of 16 bit. Think the alignment issues should be worked out now. Did some other testing with MSP430 Forth. Simplified the test case a bit by about 10-20 lines.
Cleaned up things some more. Removed utility functions that the library function basically did the same thing.Overall, the code is shaping up to be in fairly good shape to submit. I'll likely spend a bit more time on it before submitting, but I don't think I'll be able to get to the more cowbell piece that's not judged anyways.
I got the tests passing. Though, I may reevaluate how I'm readingthe binary. I also went through and fixed go vet and go lint issues. I the better commented the code.
Started reading data today and modifying things as needed. Moved some things into smaller functions.I think I know what all but two bytes of the datafile is now. Right now they're read and labeled with a /* ??? */ comment. I also have the first part converting from the raw file structure into the higher level structure.
It's not great having only a few minutes at a time to work on this, but I have the Stringer methods for most of the data structure working and a best guess data structure for the binary file.
Did a bit more on my lunch break for this. Nothing to really show yet.
I make take a break form MSP430 Forth and Pipeln to try out Go Challenge. I didn't spend much time coding, as most of my time was evaluating the binary files.
Played around with the minimal Forth I pulled out and think I've figure out why IP was going to 0. So I pulled in more words to have a closer to realistic test (QUIT, RZ, RSPSTORE, & BRANCH.)
Spent my time tonight ripping out everything but what was needed to test some things. Specifically it still had NEXT, DOCOL, main, a word, and an assembly code word. I believe I've tracked the problems I've been having to the way the instruction pointer is handled in the inner interpreter. I'll probably spend tomorrow diagramming out the memory & program flow. It's nice to have the problem narrowed down more. It's much less nice not knowing exactly how to solve said issue.
I spent a fair amount of time moving code out of the main (only) source file into smaller files. I first pulled the macros into a header, then I pulled groups of word definitions into separate files, and finally fixed compilation errors. I ended up needing to declare more labels as global. In addition to that, I also implemented the rest of the comparison operations, fixed some potential problems, and finished finished the implementation for another word. I think I'm down to the last 9 words to implement (and some have partial implementations.)
Didn't get much actually done today. I mostly fought with GCC and Binutils. Specifically, the linker and linker scripts and trying to compile with -nostdlib. I may skip this bit for now and come back to it as the stdlib works for now.
Went through and added TODO markers for all incomplete words. Made stubs for several subroutines. Implemented MUL & DIVMOD as well as untested >CFA & INTERPRET.
I think I mentioned this before, but the one thing I dislike about MSP430 assembly is the lack of multiplication & division mnenomics. That said, the naive multiply function is trivial:
/* Arguments are passed in r12 & r13, r15 is used to store the result */ clr r15 1: add r12, r15 /* ignores overflow */ dec r13 jnz 1b /* To comply with the MSP430 GCC calling convension, the result would be put back into r12 */
Division is a bit more complicated, but still didn't seem too bad. I'm not posting that because I haven't done any verification of it yet. This one at least had minimal testing in isolation.
Wrote a little bit of Go code and developed a better understood a simple checksumming algorithm. Also read through most of the Elm syntax at http://elm-lang.org/learn/Syntax.elm
Keeping it short since it's really late. Did a bit of Ember.js with Go and finally understand how Ember templates have to be included since there isn't an asset pipeline that embeds the Handlebars templates into the file. I could add that to pipeln, but that means I'll need to get more into filters to allow it to be extensible.
I then spent a fair amount of time with MSP430 Forth running it on an MSP430G2553 setting breakpoints and single stepping. Things seem to work up to a point, and I figured out where it's failing. However, I'm not 100% sure what needs to happen to fix it. Need to sleep on it.
I should have realized this, but using something newly written is a great way to get distracted by finding bugs in it. I spent most of my time fixing issues that cropped up in pipeln. On the plus side, it makes that project better. On the flip-side, I didn't really get that much done with Ember.js tonight. I did get a little done, but it felt like there was a fair amount of time getting my tmux session and VIM ctrlspace workspace(s) setup.
Most of the time was working on an Ember.js application and really getting everything ready to go to fully start learning the framework. During this process I fixed a couple issues with pipeln's javascript loading via requires. One issue was it wasn't processing a file that was included with a require. However, require_tree seemed to be working as expected. Looking at the code, it ended up being pretty obvious that the processing wasn't being called there, but it was being called from the require tree function.
Once that was fixed, things started loading, but the javascript was then breaking on the client side. Turns out, another thing I sort of arbitrarily decided when writing the initial implementation of the asset loader was to collect all require statements, then go though each processing as required, and finally prepending them to the file.This can pretty easily cause errors with undefined variables after it's loaded into the browser. My solution was to include the files processed from require/require_tree statements at the site they're declared at. This way, if the require is at the bottom of the file, it loads the file at the bottom.
I also played around a little with Bourbon, Neat, & Bitters in so far as to give up on them for now since the Sass processing isn't built into pipeln yet. I briefly looked at options for building them outside of that. Manually compiling the Sass also only yielded about 200 lines of CSS with the imports for the three libraries. As that seemed like a mistake, I decided to table that for now and go with Bootstrap.
Earlier today I spent some time with MSP430 Forth cleaning up some things and committing some code that's been hanging out uncommitted for several days now.
Didn't get much done tonight. Found the msp430-elf-run command. Fixed some things when running it.
Keeping it short tonight since I've been terrible about sleeping a proper amount at night.
Shortly after posting last night, I remembered that I should be looking at the linker script for hints as to what it's expecting. Sure enough, up by the top there's something like:
__interrupt_vector_9 : { KEEP (*(__interrupt_vector_9 )) KEEP (*(__interrupt_vector_timer0_a1)) } > VECT9
So, of course I tested the human readable version
.macro SECTION_VECTOR vector .section __interrupt_vector_\vector,"ax",@progbits .endm .global test_int SECTION_VECTOR timer0_a1 .word test_int .text test_int: push r9 mov #9, r9 pop r9 reti
Compiled it and did an objdump -S:
Disassembly of section __interrupt_vector_9: 0000fff0 <__interrupt_vector_9>: fff0: 2e c1 interrupt service routine at 0xc12e 0000c12e <test_int>: c12e: 09 12 push r9 ; c130: 39 40 09 00 mov #9, r9 ; c134: 39 41 pop r9 ; c136: 00 13 reti
So there you have it. Mystery solved (or at least, was a mystery to me.) They were nice enough to allow a tolower version of the vector name appended to __interrupt_vector_ be used to lookup the expected name. This was much easier than the weird preprocessor macro expansion I was trying to get working last night.
Post a comment
Well post progress. Don't be afraid of being seen to fail.