Filska
Filska (pronounced "full-ska", Shetland for "high spirited fun") is an esoteric programming language designed to answer the question: what is it like to program in a language where each subprogram can manipulate only a single memory location?
Rationale
Filska is a simple language similar to assembly. It's used to explore programming in a constrained environment. A Filska program may have multiple subprograms, but each subprogram gets only a single floating-point memory location for data. Additionally, there are three floating-point registers, X, Y, and Z, for moving data between subprograms.
Filska is unstructured. To move around within a subprogram, use GTO ("goto") with an offset from the current instruction. There are two options for moving between subprograms: JMP ("jump") and JPR ("jump with reset"). Each subprogram maintains its own program counter. Moving to another subprogram with JMP does not reset this counter, so moving back to the subprogram continues execution with the next instruction. Moving with JPR does reset the counter so returning to the subprogram begins again at the first instruction. When the final instruction of a subprogram is executed, the program counter automatically resets to zero and execution continues (implied looping). There is no execution stack, subprograms are not subroutines.
Filska supports the full range of mathematical operators making mathematical examples the natural target for the language.
Filska is featured in Chapters 12 and 13 of the book Strange Code: Esoteric Languages That Make Programming Fun Again (No Starch Press, 2022).
Examples
Pi
Estimate π using random numbers:
{ main
set,0
tmy " Y=0
jmp,incS " S++
rnd
tmz
mul,m=mz
tmx
rnd
tmz
mul,m=mz
add,m=mx " x^2+y^2
cmp,1
tst,l,2
gto,2
jmp,incC
set,1
tmy
jmp,incC
tzm
jmp,incS
div,m=mz
tmz
jmp,print
}
{ print
set,4
mul,m=mz
prt
set,10
chr
jpr,main
}
{ incS
swp,my
cmp,1
tst,e,4
swp,my
inc
jpr,main
swp,my
tmz
jpr,main
}
{ incC
swp,my
cmp,1
tst,e,4
swp,my
inc
jpr,main
swp,my
tmz
jpr,main
}
Roots
Calculate the roots of a quadratic equation:
{ main
" Get a, b, and c
jmp,getA
jmp,getB
jmp,getC
" Calculate D
jmp,getA " X=a
set,4 " M=4
mul,m=mx " M = M*X (4a)
jmp,getC " X=c
mul,m=mx " M = M*X (4ac)
neg " M = -M (-4ac)
tmz " Z = M (-4ac)
jmp,getB " X=b
txm " M=b
mul,m=mx " M = M*X (b*b)
add,m=mz " M = M+Z (b*b - 4ac)
tmy " Y = D (disc)
jmp,getA " X = a
txm " M = X
tmz " Z = M (a)
jmp,getB " X = b (b)
tym " M = Y (disc)
cmp,0 " compare(M,0)
tst,g,3 " D > 0 --> positive
tst,e,3 " D == 0 --> equal
tst,l,3 " D < 0 --> negative
jmp,positive
jmp,equal
jmp,negative
}
" Calculate roots w/Z == a, Y == D, X == b
{ positive
set,2 " M = 2
mul,m=mz " M = 2a
div,m=xm " M = b/(2a)
neg " M = -b/(2a)
jmp,rest " X = sqr(Y)/(2a)
jmp,?double
add,y=mx " Y = M + X (-b/(2a)+sqr(D)/(2a))
jmp,?double
sub,y=mx " Y = M - X (-b/(2a)-sqrt(D)/(2a))
jmp,?double
}
{ rest
set,2
mul,x=mz
tym
sqr
div,x=mx
jmp,positive
}
{ ?double
set,10 chr
set,49 chr
set,115 chr
set,116 chr
set,32 chr
set,114 chr
set,111 chr chr
set,116 chr
set,58 chr
set,32 chr
jmp,positive
tym
prt
set,10 chr
set,50 chr
set,110 chr
set,100 chr
set,32 chr
set,114 chr
set,111 chr chr
set,116 chr
set,58 chr
set,32 chr
jmp,positive
tym
prt
set,10 chr
hlt
}
{ equal
set,2 " M = 2
mul,m=mz " M = 2a
div,m=xm " M = b/(2a)
neg " M = -b/(2a)
jmp,?single
prt " print single root
set,10
chr
hlt
}
{ ?single
set,10 chr
set,79 chr
set,110 chr
set,101 chr
set,32 chr
set,114 chr
set,111 chr chr
set,116 chr
set,58 chr
set,32 chr
jmp,equal
}
{ negative
set,2 " M = 2
mul,m=mz " M = 2a
div,m=xm " M = b/(2a)
neg " M = -b/(2a)
swp,mz " M <--> Z
jmp,stash
swp,mz " M <--> Z
jmp,resti " X = sqr(-Y)/(2a)
jmp,?imag " '1st root: '
prt
set,43 chr
txm
prt
set,105 chr
set,10 chr
jmp,?imag " '2nd root: '
jmp,stash
tzm
prt
set,45 chr
txm
prt
set,105 chr
set,10 chr
hlt
}
{ stash
tzm
jmp,negative
tmz
jmp,negative
}
{ ?imag
" 'Complex roots: '
set,10 chr
set,67 chr
set,111 chr
set,109 chr
set,112 chr
set,108 chr
set,101 chr
set,120 chr
set,32 chr
set,114 chr
set,111 chr chr
set,116 chr
set,115 chr
set,58 chr
set,32 chr
jmp,negative
" ' '
set,32
chr chr chr chr chr
chr chr chr chr chr
chr chr chr chr chr
jmp,negative
}
{ resti
set,2
mul,x=mz
tym
neg
sqr
div,x=mx
jmp,negative
}
" Ask for and return a,b, and c
{ getA
set,65 chr
set,63 chr
set,32 chr
ipt
jmp,main
tmx
jmp,main
gto,-2
}
{ getB
set,66 chr
set,63 chr
set,32 chr
ipt
tmx
jmp,main
gto,-2
}
{ getC
set,67 chr
set,63 chr
set,32 chr
ipt
tmx
jmp,main
gto,-2
}
Computational class
Filska supports an arbitrary number of subprograms that can be configured to act like memory locations. Filska might be Turing complete.