I was able to spend a few more hours steering some sessions and managed to get a few things done.
$ cloc src
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
Crystal 34 799 1626 7828
-------------------------------------------------------------------------------
- Naive ARC (Automatic Reference Counting, ala Swift) with
--check-leaks option to instrument reference counting and validate things on program exit:
lib LibC
fun printf(format : Pointer(UInt8), ...) : Int32
end
class Point
def initialize(@x : Int32, @y : Int32)
end
end
i = 0
while i < 3
p = Point.new(i, i)
i = i + 1
end
LibC.printf("done\n")
$ bin/jasper run --check-leaks examples/leaky.jasper
jasper: 3 live allocation(s) at exit
done # exit 1
- Per-method incremental compilation: change a method, only that code gets recompiled. Relocate a method to another file, if no change to the method itself, no recompilation necessary:
# examples/wordcount.jasper
require "./tokenizer"
lib LibC
fun printf(format : Pointer(UInt8), ...) : Int32
end
text = "the quick brown fox jumps over the lazy dog"
scanner = Tokenizer.new(text)
words = 0
longest = 0
length = scanner.next_word_size
while length >= 0
words += 1
longest = length if length > longest
length = scanner.next_word_size
end
LibC.printf("%d words, longest %d\n", words, longest)
# examples/tokenizer.jasper
class Tokenizer
def initialize(@text : String)
@pos = 0
end
def space?(b : UInt8) : Bool
b == 32_u8 || b == 10_u8 || b == 9_u8
end
# Length of the next word, or -1 when the text is exhausted.
def next_word_size : Int32
size = @text.size
while @pos < size && space?(@text.byte_at(@pos))
@pos = @pos + 1
end
return -1 if @pos >= size
length = 0
while @pos < size && !space?(@text.byte_at(@pos))
length = length + 1
@pos = @pos + 1
end
length
end
end
$ bin/jasper run --stats examples/wordcount.jasper
Parse 00:00:00.0008 (0.50MB)
Semantic: register classes 00:00:00.0000 (0.50MB)
Semantic: declare signatures 00:00:00.0001 (0.50MB)
Semantic: type check 00:00:00.0002 (0.50MB)
Semantic: flow analysis 00:00:00.0000 (0.50MB)
Semantic: hierarchy layout 00:00:00.0000 (0.50MB)
Semantic: checks 00:00:00.0000 (0.50MB)
Semantic: ARC synthesis 00:00:00.0000 (0.50MB)
Codegen (myc IR) 00:00:00.0019 (0.75MB)
Backend (myc) 00:00:00.0761 (1.44MB)
Cache 2 hits, 13 misses (myc-qbe 24ce939d128c)
Link (cc) 00:00:00.0274 (1.44MB)
9 words, longest 5
- Abstract classes, and basic inheritance, even with ivar coverage (to catch corner cases):
lib LibC
fun printf(format : Pointer(UInt8), ...) : Int32
end
abstract class Shape
def initialize(@name : String)
end
def name : String
@name
end
end
class Circle < Shape
def initialize(value : Bool)
return if value
@name = "Circle"
end
end
c = Circle.new(true)
# the next line is invalid memory in Crystal
LibC.printf("name=%s\n", c.name)
In Jasper does not even compile:
$ bin/jasper run 1.jasper
1.jasper:16:5: error: `Circle#initialize` must call `super` to initialize `@name`
return if value
^^^^^^
But of course, nothing else for the time being, just playing with some theories, there is no cross-platform, stdlib, channels, fibers, not even unions 
Just having some fun, learning a bit about those things that always was interested to see them at work and never had the opportunity to get to this point (only did 1 refactoring so far).
Cheers!