spitewaste 0.1.001

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +8 -0
  3. data/README.md +55 -0
  4. data/Rakefile +10 -0
  5. data/TUTORIAL.md +125 -0
  6. data/bin/spw +10 -0
  7. data/demo/factorial-nicespace.png +0 -0
  8. data/demo/factorial.asm +47 -0
  9. data/demo/factorial.png +0 -0
  10. data/demo/factorial.wsa +5 -0
  11. data/lib/spitewaste.rb +35 -0
  12. data/lib/spitewaste/assembler.rb +56 -0
  13. data/lib/spitewaste/cli.rb +51 -0
  14. data/lib/spitewaste/cli/asm.rb +10 -0
  15. data/lib/spitewaste/cli/compile.rb +60 -0
  16. data/lib/spitewaste/cli/convert.rb +53 -0
  17. data/lib/spitewaste/cli/exec.rb +43 -0
  18. data/lib/spitewaste/cli/image.rb +53 -0
  19. data/lib/spitewaste/emitter.rb +10 -0
  20. data/lib/spitewaste/emitters/assembly.rb +7 -0
  21. data/lib/spitewaste/emitters/codegen.rb +72 -0
  22. data/lib/spitewaste/emitters/image.rb +135 -0
  23. data/lib/spitewaste/emitters/linefeed.png +0 -0
  24. data/lib/spitewaste/emitters/schemes.yaml +1143 -0
  25. data/lib/spitewaste/emitters/whitespace.rb +14 -0
  26. data/lib/spitewaste/emitters/wsassembly.rb +7 -0
  27. data/lib/spitewaste/libspw/array.spw +82 -0
  28. data/lib/spitewaste/libspw/bits.spw +72 -0
  29. data/lib/spitewaste/libspw/case.spw +32 -0
  30. data/lib/spitewaste/libspw/fun.spw +42 -0
  31. data/lib/spitewaste/libspw/io.spw +39 -0
  32. data/lib/spitewaste/libspw/math.spw +117 -0
  33. data/lib/spitewaste/libspw/prime.spw +46 -0
  34. data/lib/spitewaste/libspw/random.spw +10 -0
  35. data/lib/spitewaste/libspw/stack.spw +84 -0
  36. data/lib/spitewaste/libspw/string.spw +233 -0
  37. data/lib/spitewaste/libspw/syntax.spw +2 -0
  38. data/lib/spitewaste/libspw/test.spw +8 -0
  39. data/lib/spitewaste/libspw/util.spw +98 -0
  40. data/lib/spitewaste/parsers/assembly.rb +35 -0
  41. data/lib/spitewaste/parsers/fucktional.rb +72 -0
  42. data/lib/spitewaste/parsers/spitewaste.rb +192 -0
  43. data/lib/spitewaste/parsers/whitespace.rb +60 -0
  44. data/lib/spitewaste/version.rb +3 -0
  45. data/spitewaste.gemspec +17 -0
  46. metadata +88 -0
@@ -0,0 +1,14 @@
1
+ module Spitewaste
2
+ class WhitespaceEmitter < Emitter
3
+ def emit io:
4
+ instructions.each do |op, arg|
5
+ io.write OPERATORS_M2T[op]
6
+ io.write self.class.encode(arg) if arg
7
+ end
8
+ end
9
+
10
+ def self.encode n
11
+ (n < 0 ? ?\t : ' ') + n.abs.to_s(2).tr('01', " \t") + ?\n
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,7 @@
1
+ module Spitewaste
2
+ class WSAssemblyEmitter < Emitter
3
+ def emit io:
4
+ io.puts @instructions # actually just preprocessed Spitewaste
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,82 @@
1
+ $amax = 1000
2
+
3
+ arysum: reduce (add) ret
4
+
5
+ arydup:
6
+ dup $++ push -2 copy 1 store
7
+ times (push -2 load $-- :ncopy) ret
8
+
9
+ arypop: slide 1 $-- ret
10
+
11
+ aryshift: dup :dig $-- ret
12
+
13
+ arycat: dup $++ :roll add ret
14
+
15
+ arypack:
16
+ :arydup reduce (:max) $++ push -1 swap store
17
+ $-- times (push -1 load mul add)
18
+ push $amax mul push -1 load add
19
+ push $amax mul push -10 load add ret
20
+
21
+ aryunpack:
22
+ push $amax :divmod push -2 swap store
23
+ push $amax :divmod push -1 swap store
24
+ push -2 load times (push -1 load :divmod swap)
25
+ push 2 sub load ret
26
+
27
+ arylen: push $amax mod ret
28
+
29
+ ;;;
30
+
31
+ aryindex: copy 1 ; two copies of length, one gets decremented, index is diff
32
+ _aryindex_loop: ; [h n l]
33
+ dup jn _aryindex_notfound
34
+ dup push 2 add :roll copy 2 :eq jz _aryindex_no
35
+ copy 2 copy 1 sub swap $++ :nslide ret
36
+
37
+ _aryindex_no: $-- jump _aryindex_loop
38
+
39
+ _aryindex_notfound: slide 1 ret
40
+
41
+ ;;;
42
+
43
+ ; element at index i
44
+ aryat: ; [a i]
45
+ dup jn _aryat_neg
46
+ copy 1 swap sub dup :pos? jz _aryat_oob
47
+ :roll swap $-- :nslide ret
48
+
49
+ _aryat_neg: copy 1 add dup jn _aryat_oob jump aryat
50
+
51
+ _aryat_oob: push "(aryat) index out of bounds!" :die
52
+
53
+ minmax:
54
+ :arydup reduce (:max)
55
+ push -1 swap store
56
+ reduce (:min) push -1 load ret
57
+
58
+ ;;;
59
+
60
+ sort: push -3 copy 1 store ; preserve length
61
+ _sort_loop:
62
+ :arydup reduce (:min)
63
+ push -1 copy 1 store copy 1 $++ :bury ; stash minimum element
64
+ :arydup push -1 load :aryindex
65
+ copy 1 swap sub :dig $-- ; remove minimum element from array
66
+ push 0 copy 1 sub jn _sort_loop
67
+ push 3 sub load ret
68
+
69
+ aryrev: push -3 copy 1 store
70
+ _aryrev_loop:
71
+ swap copy 1 :bury $--
72
+ push 0 copy 1 sub jn _aryrev_loop
73
+ push 3 sub load ret
74
+
75
+ ;;;
76
+
77
+ aryrep: push -1 swap push -3 copy 1 store store
78
+ _aryrep_loop:
79
+ push -1 dup :dec load jz _aryrep_done
80
+ :arydup jump _aryrep_loop
81
+
82
+ _aryrep_done: push -3 load $-- times (:arycat) ret
@@ -0,0 +1,72 @@
1
+ import math
2
+
3
+ ; TODO: don't use strings for bitwise operations
4
+
5
+ ; bitwise bitwise_and
6
+ ; ! clobbers heap address -1
7
+ bitwise_and: ; [a b] => [a & b]
8
+ push -1 push 0 store ; empty string tally
9
+
10
+ _bitwise_and_loop:
11
+ copy 1 copy 1 add jz _bitwise_done
12
+ copy 1 push 2 mod
13
+ copy 1 push 2 mod
14
+ add push 2 sub jz _bitwise_and_yes
15
+ push '0' jump _bitwise_and_update
16
+
17
+ _bitwise_and_yes: push '1'
18
+ _bitwise_and_update: :_bitwise_update jump _bitwise_and_loop
19
+
20
+ _bitwise_update:
21
+ push -1 load swap :strcat
22
+ push -1 swap store
23
+ push 2 div swap push 2 div ret
24
+
25
+ _bitwise_done: push -1 load :strrev :bin slide 2 ret
26
+
27
+ ; bitwise bitwise_or
28
+ ; ! clobbers heap address -1
29
+ bitwise_or: ; [a b] => [a | b]
30
+ push -1 push 0 store ; empty string tally
31
+
32
+ _bitwise_or_loop:
33
+ copy 1 copy 1 add jz _bitwise_done
34
+ copy 1 push 2 mod
35
+ copy 1 push 2 mod
36
+ add jz _bitwise_or_no
37
+ push '1' jump _bitwise_or_update
38
+
39
+ _bitwise_or_no: push '0'
40
+ _bitwise_or_update: :_bitwise_update jump _bitwise_or_loop
41
+
42
+ ; bitwise bitwise_xor
43
+ ; ! clobbers heap address -1
44
+ bitwise_xor: ; [a b] => [a ^ b]
45
+ push -1 push 0 store ; empty string tally
46
+
47
+ _bitwise_xor_loop:
48
+ copy 1 copy 1 add jz _bitwise_done
49
+ copy 1 push 2 mod
50
+ copy 1 push 2 mod
51
+ add push 1 sub jz _bitwise_xor_yes
52
+ push '0' jump _bitwise_xor_update
53
+
54
+ _bitwise_xor_yes: push '1'
55
+ _bitwise_xor_update: :_bitwise_update jump _bitwise_xor_loop
56
+
57
+ ; flip all bits in n ; [n]
58
+ bitwise_not:
59
+ dup push 0 swap push 1 add sub
60
+ swap push 2 :ilog push 2 swap :pow mod ret
61
+
62
+ ;;;
63
+
64
+ ; number of set bits in n ; [n]
65
+ popcount: push 2 :digits reduce (add) ret
66
+
67
+ ;;;
68
+
69
+ ; most significant set bit in n, as a power of 2 ; [n]
70
+ msb: dup jz _msb_zero
71
+ push 2 :itos :strlen $-- push 2 swap :pow ret
72
+ _msb_zero: ret
@@ -0,0 +1,32 @@
1
+ import bits
2
+ ;;; Case conversion
3
+
4
+ upcase: :strunpack push 0 ; tally
5
+ _upcase_loop:
6
+ swap dup jz _upcase_done
7
+ dup :isalpha jz _upcase_cat
8
+ push 95 :bitwise_and
9
+ _upcase_cat:
10
+ :strcat jump _upcase_loop
11
+
12
+ _upcase_done: pop ret
13
+
14
+ downcase: :strunpack push 0 ; tally
15
+ _downcase_loop:
16
+ swap dup jz _downcase_done
17
+ dup :isalpha jz _downcase_cat
18
+ push 32 :bitwise_or
19
+ _downcase_cat:
20
+ :strcat jump _downcase_loop
21
+
22
+ _downcase_done: pop ret
23
+
24
+ swapcase: :strunpack push 0 ; tally
25
+ _swapcase_loop:
26
+ swap dup jz _swapcase_done
27
+ dup :isalpha jz _swapcase_cat
28
+ push 32 :bitwise_xor
29
+ _swapcase_cat:
30
+ :strcat jump _swapcase_loop
31
+
32
+ _swapcase_done: pop ret
@@ -0,0 +1,42 @@
1
+ import string
2
+
3
+ palindrome?: dup :strrev :eq ret
4
+
5
+ ;;;
6
+
7
+ anagrams?:
8
+ :strunpack push 0 :to_a :sort :strjoin swap
9
+ :strunpack push 0 :to_a :sort :strjoin :eq ret
10
+
11
+ ;;;
12
+
13
+ isop: :upcase push 0 swap ; tally
14
+ _isop_loop: ; [t s]
15
+ dup jz _isop_done
16
+ swap copy 1 push 128 mod
17
+ dup :isalpha jz _isop_no ; ignore non-alphabetical
18
+ push 64
19
+ _isop_resume:
20
+ sub add
21
+ swap push 128 div jump _isop_loop
22
+
23
+ _isop_no: dup jump _isop_resume
24
+
25
+ _isop_done: pop ret
26
+
27
+ ;;;
28
+
29
+ collatz: push 1 ; sequence length
30
+ _collatz_loop:
31
+ copy 1 dup push 1 sub jz _collatz_done
32
+ dup push 2 mod ; m2 n m2
33
+ swap copy 1 push 2 mul $++ mul
34
+ push 2 copy 2 sub div add
35
+ swap $++ jump _collatz_loop
36
+
37
+ _collatz_done: pop ret
38
+
39
+ ;;;
40
+
41
+ ruby:
42
+ push "'" :strcat push "ruby -e 'p " swap :strcat shell ret
@@ -0,0 +1,39 @@
1
+ ; prints the character at the top of the stack until terminating zero
2
+ print: :strunpack
3
+ _print_loop:
4
+ dup jz _print_done
5
+ ochr jump _print_loop
6
+ _print_done: pop ret
7
+
8
+ ; print with newline
9
+ println: :print push 10 ochr ret
10
+
11
+ ;;;
12
+
13
+ ; reads a line of input onto the top of the stack as a packed string
14
+ ; ! clobbers heap address -1
15
+ getline: push 0 ; terminator for strpack
16
+
17
+ ; read characters onto the stack until newline (10) or EOF (-1)
18
+ _getline_loop:
19
+ push -1 dup ichr load
20
+ dup jn _getline_eof
21
+ dup push 10 sub jz _getline_done
22
+ jump _getline_loop
23
+
24
+ _getline_eof: pop
25
+ _getline_done: :strpack :strrev ret
26
+
27
+ ;;;
28
+
29
+ prompt: :print :getline ret
30
+
31
+ ;;;
32
+
33
+ ; consume stdin until EOF
34
+ readall: push 0 ; accumulated string
35
+ _readall_loop:
36
+ :getline dup jz _readall_done
37
+ :strcat jump _readall_loop
38
+
39
+ _readall_done: pop ret
@@ -0,0 +1,117 @@
1
+ import util (range) ; for factorial
2
+
3
+ ; [b e] => [b^e]
4
+ pow:
5
+ push 1 swap
6
+
7
+ _pow_loop: ; [b n e]
8
+ dup jz _pow_done
9
+ swap copy 2 mul ; [b e n*b]
10
+ swap push 1 sub jump _pow_loop
11
+
12
+ _pow_done: ; b n e
13
+ pop slide 1 ret
14
+
15
+ ;;;
16
+
17
+ ; [n] => [n!]
18
+ factorial: push 0 swap :range
19
+ _fac_loop: swap dup jz _fac_done mul jump _fac_loop
20
+ _fac_done: pop ret
21
+
22
+ ;;;
23
+
24
+ isqrt: ; [n] -> [isqrt(n)]
25
+ dup push 2 sub jn _isqrt_done
26
+ dup push 4 div :isqrt push 2 mul
27
+ dup push 1 add
28
+ copy 2 copy 1 dup mul sub jn _isqrt_cleanup
29
+ swap
30
+ _isqrt_cleanup: swap slide 2
31
+ _isqrt_done: ret
32
+
33
+ ;;;
34
+
35
+ ; intger logarithm ; [a b] => [log(a, b)]
36
+ ; ! clobbers heap address -1 TODO: maybe not necessary?
37
+ ilog:
38
+ push -1 push 0 store ; tally
39
+
40
+ _ilog_loop: ; a b
41
+ swap dup jz _ilog_done
42
+ push -1 :inc
43
+ copy 1 div swap
44
+ jump _ilog_loop
45
+
46
+ _ilog_done: ; a b t
47
+ push -1 load slide 2 ret
48
+
49
+ ;;;
50
+
51
+ ; greatest common divisor
52
+ gcd: ; [a b]
53
+ dup jz _gcd_done
54
+ swap copy 1 mod
55
+ jump gcd
56
+
57
+ _gcd_done: pop ret
58
+
59
+ ; least common multiple
60
+ lcm: ; [a b]
61
+ copy 1 mul
62
+ swap dup copy 2 swap div
63
+ :gcd div ret
64
+
65
+ ;;;
66
+
67
+ min: ; [a b]
68
+ copy 1 copy 1 sub jn _min_done swap
69
+ _min_done: pop ret
70
+
71
+ max: ; [a b]
72
+ copy 1 copy 1 sub jn _max_done swap
73
+ _max_done: slide 1 ret
74
+
75
+ ;;;
76
+
77
+ ; -1, 0, or 1 to indicate the sign of the argument
78
+ sign: ; [n]
79
+ dup jz _sign_zero
80
+ jn _sign_neg
81
+ push 1 ret
82
+ _sign_zero: ret
83
+ _sign_neg: push -1 ret
84
+
85
+ ; absolute value ; [n] => [abs(n)]
86
+ abs: dup :sign mul ret
87
+
88
+ ;;;
89
+
90
+ divmod:
91
+ push -1 swap store
92
+ dup push -1 load div
93
+ swap push -1 load mod ret
94
+
95
+ ;;;
96
+
97
+ pos?: :sign push 1 :eq ret
98
+ neg?: :sign push -1 :eq ret
99
+
100
+ ;;;
101
+
102
+ divisors: ; [n]
103
+ dup push -1 swap store ; preserve n because array operations
104
+ :isqrt push 1 swap :range dup ; 1..n**0.5
105
+ reject (push -1 load swap mod) :arydup ; get first half of divisors
106
+ map (push -1 load swap div) :arycat ; map first half to second half
107
+ push -1 load copy 2 dup mul sub jz _divisors_square
108
+ ret
109
+
110
+ _divisors_square: slide 1 $-- ret ; de-duplicate when N is a perfect square
111
+
112
+ ;;;
113
+
114
+ nCk:
115
+ copy 1 copy 1 sub :factorial
116
+ swap :factorial mul
117
+ swap :factorial swap div ret
@@ -0,0 +1,46 @@
1
+ ; [n] => [0|1]
2
+ prime?: ; [n]
3
+ dup push 3 sub jn _prime_special ; special-case < 3
4
+ dup push 2 mod jz _prime_even ; otherwise, even -> false
5
+ push 3
6
+
7
+ _prime_loop: ; [n d]
8
+ copy 1 copy 1 dup mul sub jn _prime_yes ; divisor > isqrt(n), n is prime
9
+ copy 1 copy 1 mod jz _prime_no
10
+ push 2 add jump _prime_loop
11
+
12
+ _prime_yes:
13
+ pop dup div ret ; return 1
14
+
15
+ _prime_even:
16
+ push 1
17
+ _prime_no:
18
+ pop dup sub ret ; return 0
19
+
20
+ _prime_special: ; [n]
21
+ push 2 sub jz _prime_two
22
+ push 0 ret ; false for n < 2
23
+
24
+ _prime_two:
25
+ push 1 ret
26
+
27
+ ;;;
28
+
29
+ next_prime: push 1 add dup :prime? jz next_prime ret
30
+
31
+ ;;;
32
+
33
+ ; prime factorization
34
+ factor: ; [n]
35
+ push 2 swap ; initial divisor
36
+ push -2,0 store ; number of prime factors
37
+ _factor_loop: ; [d n]
38
+ dup push 2 sub jn _factor_done
39
+ jump _divisor_loop ; prevent dead code elimination :(
40
+ _divisor_loop:
41
+ dup copy 2 :divmod jz _divisor_keep
42
+ pop swap :next_prime swap jump _factor_loop
43
+
44
+ _divisor_keep: push -2 :inc slide 1 copy 1 swap jump _factor_loop
45
+
46
+ _factor_done: slide 1 push 3 sub load ret