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.