kapusta 0.8.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +8 -2
- data/bin/check-all +17 -0
- data/bin/compile-examples +70 -0
- data/bin/fennel-parity +4 -37
- data/examples/account-lockout.kap +11 -0
- data/examples/circle.kap +16 -0
- data/examples/convert-temperature.kap +14 -0
- data/examples/count-effects.kap +13 -0
- data/examples/falling-drops.kap +12 -0
- data/examples/fennel-parity-examples.txt +40 -0
- data/examples/hit-counter.kap +17 -0
- data/examples/max-achievable.kap +8 -0
- data/examples/mruby-runtime-examples.txt +89 -0
- data/examples/number-of-1-bits.kap +13 -0
- data/examples/number-of-steps.kap +15 -0
- data/examples/parking-system.kap +18 -0
- data/examples/thread-styles.kap +41 -0
- data/examples/two-sum-hash.kap +11 -14
- data/examples/underscore-patterns.kap +1 -1
- data/lib/kapusta/ast.rb +1 -1
- data/lib/kapusta/cli.rb +11 -6
- data/lib/kapusta/compiler/emitter/bindings.rb +27 -2
- data/lib/kapusta/compiler/emitter/control_flow.rb +97 -14
- data/lib/kapusta/compiler/emitter/interop.rb +2 -0
- data/lib/kapusta/compiler/emitter/patterns.rb +125 -0
- data/lib/kapusta/compiler/emitter/support.rb +9 -2
- data/lib/kapusta/compiler/emitter.rb +2 -1
- data/lib/kapusta/compiler/normalizer.rb +22 -12
- data/lib/kapusta/compiler.rb +13 -4
- data/lib/kapusta/errors.rb +3 -0
- data/lib/kapusta/formatter.rb +9 -2
- data/lib/kapusta/lsp/scope_walker.rb +55 -5
- data/lib/kapusta/reader.rb +28 -0
- data/lib/kapusta/version.rb +1 -1
- data/lib/kapusta.rb +2 -2
- data/spec/cli_spec.rb +35 -0
- data/spec/examples_spec.rb +128 -0
- data/spec/lsp_spec.rb +86 -0
- data/spec/spec_helper.rb +9 -0
- metadata +14 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3cafef3668504ca08a40ba087c4c2b754bfda02e6f61161f19bcf8d56a254e00
|
|
4
|
+
data.tar.gz: 501b99f6ec3bfa950865b63b26ec6fd7f5b64977bb86f41d4eff51957602cc84
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b774d8f0bbd772e223743a2ec844bec4949a6f1a5a545767c3b608c8ec0c2da055fe9537c68a3cf57573ac80ed75d11d85884245b4fcbd401af16646aaab5283
|
|
7
|
+
data.tar.gz: 10b6d3f30fdfc760569c40c70e22f2b63dcf124ea3de3cffca2f061642523bc7057c878b81460181950356193c5786a35df28d4fd2b4859c1c38bc2285392f40
|
data/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Kapusta is a Lisp for the Ruby runtime.
|
|
|
4
4
|
|
|
5
5
|
It is inspired by [Fennel](https://fennel-lang.org). It is not intended to be production-ready like Clojure: that would be a lot of work, and Ruby is already a rich, elegant language.
|
|
6
6
|
|
|
7
|
-
Instead, Kapusta aims to bring some of the simplicity and joy of Lisp to Ruby. Where
|
|
7
|
+
Instead, Kapusta aims to bring some of the simplicity and joy of Lisp to Ruby. Where Fennel uses Lua's stdlib and runtime, Kapusta uses Ruby's. You can use it for small apps, LeetCode, DragonRuby, or maybe even Rails.
|
|
8
8
|
|
|
9
9
|
For more information about Kapusta, see the official Fennel documentation and tutorials.
|
|
10
10
|
|
|
@@ -45,6 +45,12 @@ exe/kapusta --compile examples/fizzbuzz.kap > examples/fizzbuzz.rb
|
|
|
45
45
|
ruby examples/fizzbuzz.rb
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
+
For mruby-compatible output, such as DragonRuby, use:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
exe/kapusta --compile --target=mruby examples/match.kap > examples/match-mruby.rb
|
|
52
|
+
```
|
|
53
|
+
|
|
48
54
|
## Use from Ruby
|
|
49
55
|
|
|
50
56
|
Ruby can require a `.kap` file and use it directly.
|
|
@@ -104,7 +110,7 @@ Kapusta keeps most core Fennel forms. The main differences come from Ruby's runt
|
|
|
104
110
|
Kapusta-specific additions:
|
|
105
111
|
|
|
106
112
|
- `module` and `class` for Ruby host structure, including file-header forms
|
|
107
|
-
- `ivar`
|
|
113
|
+
- `ivar` or `@var` / `cvar` or `@@var` / `gvar` or `$var`
|
|
108
114
|
- `try` / `catch` / `finally` plus `raise` for exceptions
|
|
109
115
|
- `(ruby "...")` raw host escape hatch
|
|
110
116
|
- a trailing symbol-keyed hash is emitted as Ruby keyword arguments
|
data/bin/check-all
CHANGED
|
@@ -16,4 +16,21 @@ bin/fennel-parity
|
|
|
16
16
|
echo "== compile examples =="
|
|
17
17
|
bin/compile-examples
|
|
18
18
|
|
|
19
|
+
echo "== run mruby-compatible examples on mruby =="
|
|
20
|
+
MRUBY_RUNTIME_EXAMPLES=()
|
|
21
|
+
while IFS= read -r example || [[ -n "$example" ]]; do
|
|
22
|
+
[[ -n "$example" ]] && MRUBY_RUNTIME_EXAMPLES+=("$example")
|
|
23
|
+
done < examples/mruby-runtime-examples.txt
|
|
24
|
+
|
|
25
|
+
for example in "${MRUBY_RUNTIME_EXAMPLES[@]}"; do
|
|
26
|
+
ruby_file="examples-compiled/$example.rb"
|
|
27
|
+
file="examples-compiled/$example-mruby.rb"
|
|
28
|
+
if [[ ! -f "$file" ]]; then
|
|
29
|
+
file="$ruby_file"
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
ruby "$ruby_file" >/dev/null
|
|
33
|
+
mruby "$file" >/dev/null
|
|
34
|
+
done
|
|
35
|
+
|
|
19
36
|
echo "== Success! =="
|
data/bin/compile-examples
CHANGED
|
@@ -4,6 +4,61 @@ set -euo pipefail
|
|
|
4
4
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
5
5
|
SOURCE_DIR="$ROOT_DIR/examples"
|
|
6
6
|
TARGET_DIR="$ROOT_DIR/examples-compiled"
|
|
7
|
+
tmp_files=()
|
|
8
|
+
MRUBY_RUNTIME_EXAMPLES=()
|
|
9
|
+
|
|
10
|
+
while IFS= read -r example || [[ -n "$example" ]]; do
|
|
11
|
+
[[ -n "$example" ]] && MRUBY_RUNTIME_EXAMPLES+=("$example")
|
|
12
|
+
done < "$SOURCE_DIR/mruby-runtime-examples.txt"
|
|
13
|
+
|
|
14
|
+
cleanup() {
|
|
15
|
+
rm -f "${tmp_files[@]}"
|
|
16
|
+
}
|
|
17
|
+
trap cleanup EXIT
|
|
18
|
+
|
|
19
|
+
is_mruby_runtime_example() {
|
|
20
|
+
local name="$1"
|
|
21
|
+
|
|
22
|
+
for example in "${MRUBY_RUNTIME_EXAMPLES[@]}"; do
|
|
23
|
+
[[ "$name" == "$example" ]] && return 0
|
|
24
|
+
done
|
|
25
|
+
|
|
26
|
+
return 1
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
needs_mruby_artifact() {
|
|
30
|
+
local name="$1"
|
|
31
|
+
local ruby_file="$2"
|
|
32
|
+
local ruby_stdout
|
|
33
|
+
local ruby_stderr
|
|
34
|
+
local mruby_stdout
|
|
35
|
+
local mruby_stderr
|
|
36
|
+
|
|
37
|
+
is_mruby_runtime_example "$name" || return 1
|
|
38
|
+
|
|
39
|
+
ruby_stdout="$(mktemp)"
|
|
40
|
+
ruby_stderr="$(mktemp)"
|
|
41
|
+
mruby_stdout="$(mktemp)"
|
|
42
|
+
mruby_stderr="$(mktemp)"
|
|
43
|
+
tmp_files+=("$ruby_stdout" "$ruby_stderr" "$mruby_stdout" "$mruby_stderr")
|
|
44
|
+
|
|
45
|
+
if ! ruby "$ruby_file" > "$ruby_stdout" 2> "$ruby_stderr"; then
|
|
46
|
+
printf 'Compiled example failed under ruby: %s\n' "$ruby_file" >&2
|
|
47
|
+
cat "$ruby_stderr" >&2
|
|
48
|
+
exit 1
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
if ! mruby "$ruby_file" > "$mruby_stdout" 2> "$mruby_stderr"; then
|
|
52
|
+
return 0
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
! cmp -s "$ruby_stdout" "$mruby_stdout"
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (($# > 0)); then
|
|
59
|
+
printf 'usage: bin/compile-examples\n' >&2
|
|
60
|
+
exit 1
|
|
61
|
+
fi
|
|
7
62
|
|
|
8
63
|
mkdir -p "$TARGET_DIR"
|
|
9
64
|
|
|
@@ -18,7 +73,22 @@ fi
|
|
|
18
73
|
for kap_file in "${kap_files[@]}"; do
|
|
19
74
|
name="$(basename "$kap_file" .kap)"
|
|
20
75
|
ruby_file="$TARGET_DIR/$name.rb"
|
|
76
|
+
mruby_file="$TARGET_DIR/$name-mruby.rb"
|
|
21
77
|
|
|
22
78
|
"$ROOT_DIR/exe/kapusta" --compile "$kap_file" > "$ruby_file"
|
|
23
79
|
printf 'Compiled %s -> %s\n' "$kap_file" "$ruby_file"
|
|
80
|
+
|
|
81
|
+
if needs_mruby_artifact "$name" "$ruby_file"; then
|
|
82
|
+
tmp_mruby="$(mktemp)"
|
|
83
|
+
tmp_files+=("$tmp_mruby")
|
|
84
|
+
"$ROOT_DIR/exe/kapusta" --compile --target=mruby "$kap_file" > "$tmp_mruby"
|
|
85
|
+
if cmp -s "$ruby_file" "$tmp_mruby"; then
|
|
86
|
+
rm -f "$mruby_file"
|
|
87
|
+
else
|
|
88
|
+
mv "$tmp_mruby" "$mruby_file"
|
|
89
|
+
printf 'Compiled %s -> %s\n' "$kap_file" "$mruby_file"
|
|
90
|
+
fi
|
|
91
|
+
else
|
|
92
|
+
rm -f "$mruby_file"
|
|
93
|
+
fi
|
|
24
94
|
done
|
data/bin/fennel-parity
CHANGED
|
@@ -9,43 +9,10 @@ EXAMPLES_ERRORS = File.join(ROOT, 'examples-errors')
|
|
|
9
9
|
KAPUSTA = File.join(ROOT, 'exe', 'kapusta')
|
|
10
10
|
KAPFMT = File.join(ROOT, 'exe', 'kapfmt')
|
|
11
11
|
|
|
12
|
-
COMPATIBLE =
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
climbing-stairs.kap
|
|
17
|
-
describe.kap
|
|
18
|
-
destructure.kap
|
|
19
|
-
even-squares.kap
|
|
20
|
-
factorial.kap
|
|
21
|
-
fib.kap
|
|
22
|
-
fizzbuzz.kap
|
|
23
|
-
gcd.kap
|
|
24
|
-
hashfn.kap
|
|
25
|
-
leap-year.kap
|
|
26
|
-
macros-dbg.kap
|
|
27
|
-
macros-import-helpers.kap
|
|
28
|
-
macros-import-whole.kap
|
|
29
|
-
macros-import.kap
|
|
30
|
-
macros-multi.kap
|
|
31
|
-
macros-swap.kap
|
|
32
|
-
macros-thrice-if.kap
|
|
33
|
-
macros-unless.kap
|
|
34
|
-
macros-when-let.kap
|
|
35
|
-
match.kap
|
|
36
|
-
min-max.kap
|
|
37
|
-
or-patterns.kap
|
|
38
|
-
power-of-three.kap
|
|
39
|
-
packet-router.kap
|
|
40
|
-
points.kap
|
|
41
|
-
primes.kap
|
|
42
|
-
safe-lookup.kap
|
|
43
|
-
shapes.kap
|
|
44
|
-
squares.kap
|
|
45
|
-
sum.kap
|
|
46
|
-
tic-tac-toe.kap
|
|
47
|
-
underscore-patterns.kap
|
|
48
|
-
].freeze
|
|
12
|
+
COMPATIBLE = File.readlines(File.join(EXAMPLES, 'fennel-parity-examples.txt'), chomp: true)
|
|
13
|
+
.reject(&:empty?)
|
|
14
|
+
.map { |name| "#{name}.kap" }
|
|
15
|
+
.freeze
|
|
49
16
|
|
|
50
17
|
def run(cmd, file, chdir: EXAMPLES, env: {})
|
|
51
18
|
out, err, status = Open3.capture3(env, cmd, file, chdir:)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
(local max-missed 3)
|
|
2
|
+
|
|
3
|
+
(fn classify [guesses]
|
|
4
|
+
(var missed 0)
|
|
5
|
+
(each [_ g (ipairs guesses)]
|
|
6
|
+
(when (= g 1) (set missed (+ missed 1))))
|
|
7
|
+
(if (< missed max-missed) :ok :locked))
|
|
8
|
+
|
|
9
|
+
(print (classify [0 1 0 1]))
|
|
10
|
+
(print (classify [1 1 1]))
|
|
11
|
+
(print (classify [1 1 1 0]))
|
data/examples/circle.kap
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
(class Circle)
|
|
2
|
+
|
|
3
|
+
(local pi 3.14159)
|
|
4
|
+
|
|
5
|
+
(fn initialize [radius]
|
|
6
|
+
(set @radius radius))
|
|
7
|
+
|
|
8
|
+
(fn area []
|
|
9
|
+
(* pi @radius @radius))
|
|
10
|
+
|
|
11
|
+
(fn circumference []
|
|
12
|
+
(* 2 pi @radius))
|
|
13
|
+
|
|
14
|
+
(let [c (Circle.new 5)]
|
|
15
|
+
(print (c.area))
|
|
16
|
+
(print (c.circumference)))
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
(local KELVIN-OFFSET 273.15)
|
|
2
|
+
(local FAHRENHEIT-SCALE 1.8)
|
|
3
|
+
(local FAHRENHEIT-OFFSET 32.0)
|
|
4
|
+
|
|
5
|
+
(fn convert-temperature [celsius]
|
|
6
|
+
(let [k (+ celsius KELVIN-OFFSET)
|
|
7
|
+
f (+ (* celsius FAHRENHEIT-SCALE) FAHRENHEIT-OFFSET)]
|
|
8
|
+
[k f]))
|
|
9
|
+
|
|
10
|
+
(let [[k f] (convert-temperature 36.5)]
|
|
11
|
+
(print k f))
|
|
12
|
+
|
|
13
|
+
(let [[k f] (convert-temperature 122.11)]
|
|
14
|
+
(print k f))
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
(fn count-by-kind [effects]
|
|
2
|
+
(var quits 0)
|
|
3
|
+
(var moves 0)
|
|
4
|
+
(each [_ effect (ipairs effects)]
|
|
5
|
+
(case (. effect :kind)
|
|
6
|
+
:quit (set quits (+ quits 1))
|
|
7
|
+
:move (set moves (+ moves 1))
|
|
8
|
+
_ nil))
|
|
9
|
+
[quits moves])
|
|
10
|
+
|
|
11
|
+
(let [effects [{:kind :move} {:kind :quit} {:kind :move} {:kind :other}]
|
|
12
|
+
[q m] (count-by-kind effects)]
|
|
13
|
+
(print q m))
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
(fn step [drops]
|
|
2
|
+
(each [_ drop (ipairs drops)]
|
|
3
|
+
(let [falling {:kind (. drop :kind)
|
|
4
|
+
:x (. drop :x)
|
|
5
|
+
:y (+ (. drop :y) (. drop :speed))
|
|
6
|
+
:w (. drop :w)
|
|
7
|
+
:h (. drop :h)
|
|
8
|
+
:speed (. drop :speed)}]
|
|
9
|
+
(print (. falling :kind) (. falling :x) (. falling :y)))))
|
|
10
|
+
|
|
11
|
+
(step [{:kind "rain" :x 0 :y 0 :w 1 :h 1 :speed 2}
|
|
12
|
+
{:kind "snow" :x 5 :y 1 :w 1 :h 1 :speed 1}])
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
ackermann
|
|
2
|
+
anonymous-greeter
|
|
3
|
+
classify-wallet
|
|
4
|
+
climbing-stairs
|
|
5
|
+
convert-temperature
|
|
6
|
+
count-effects
|
|
7
|
+
describe
|
|
8
|
+
destructure
|
|
9
|
+
even-squares
|
|
10
|
+
factorial
|
|
11
|
+
falling-drops
|
|
12
|
+
fib
|
|
13
|
+
fizzbuzz
|
|
14
|
+
gcd
|
|
15
|
+
hashfn
|
|
16
|
+
leap-year
|
|
17
|
+
macros-dbg
|
|
18
|
+
macros-import-helpers
|
|
19
|
+
macros-import-whole
|
|
20
|
+
macros-import
|
|
21
|
+
macros-multi
|
|
22
|
+
macros-swap
|
|
23
|
+
macros-thrice-if
|
|
24
|
+
macros-unless
|
|
25
|
+
macros-when-let
|
|
26
|
+
match
|
|
27
|
+
max-achievable
|
|
28
|
+
min-max
|
|
29
|
+
or-patterns
|
|
30
|
+
power-of-three
|
|
31
|
+
packet-router
|
|
32
|
+
points
|
|
33
|
+
primes
|
|
34
|
+
safe-lookup
|
|
35
|
+
shapes
|
|
36
|
+
squares
|
|
37
|
+
sum
|
|
38
|
+
thread-styles
|
|
39
|
+
tic-tac-toe
|
|
40
|
+
underscore-patterns
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
(class HitCounter)
|
|
2
|
+
|
|
3
|
+
(set @@total 0)
|
|
4
|
+
|
|
5
|
+
(fn initialize [name] (set @name name))
|
|
6
|
+
|
|
7
|
+
(fn hit []
|
|
8
|
+
(set @@total (+ @@total 1))
|
|
9
|
+
(set $last-hitter @name)
|
|
10
|
+
@@total)
|
|
11
|
+
|
|
12
|
+
(let [a (HitCounter.new "alice")
|
|
13
|
+
b (HitCounter.new "bob")]
|
|
14
|
+
(print (a.hit))
|
|
15
|
+
(print (b.hit))
|
|
16
|
+
(print (a.hit))
|
|
17
|
+
(print $last-hitter))
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
account-lockout
|
|
2
|
+
accumulator
|
|
3
|
+
ackermann
|
|
4
|
+
anagram
|
|
5
|
+
anonymous-greeter
|
|
6
|
+
bank-account
|
|
7
|
+
baseball-game
|
|
8
|
+
best-time-to-buy-sell-stock
|
|
9
|
+
binary-search
|
|
10
|
+
binary-to-decimal
|
|
11
|
+
block-sort
|
|
12
|
+
calc
|
|
13
|
+
circle
|
|
14
|
+
classify-wallet
|
|
15
|
+
climbing-stairs
|
|
16
|
+
contains-duplicate
|
|
17
|
+
convert-temperature
|
|
18
|
+
count-effects
|
|
19
|
+
counter
|
|
20
|
+
describe
|
|
21
|
+
destructure
|
|
22
|
+
doto-hygiene
|
|
23
|
+
doto
|
|
24
|
+
egg-count
|
|
25
|
+
even-squares
|
|
26
|
+
exceptions
|
|
27
|
+
factorial
|
|
28
|
+
falling-drops
|
|
29
|
+
fib
|
|
30
|
+
fizzbuzz
|
|
31
|
+
gcd
|
|
32
|
+
greet
|
|
33
|
+
happy-number
|
|
34
|
+
hashfn
|
|
35
|
+
hit-counter
|
|
36
|
+
kwargs
|
|
37
|
+
leap-year
|
|
38
|
+
length-of-last-word
|
|
39
|
+
macros-dbg
|
|
40
|
+
macros-import-helpers
|
|
41
|
+
macros-import-whole
|
|
42
|
+
macros-import
|
|
43
|
+
macros-multi
|
|
44
|
+
macros-swap
|
|
45
|
+
macros-thrice-if
|
|
46
|
+
macros-unless
|
|
47
|
+
macros-when-let
|
|
48
|
+
majority-element
|
|
49
|
+
manhattan-distance
|
|
50
|
+
match
|
|
51
|
+
max-achievable
|
|
52
|
+
maximum-subarray
|
|
53
|
+
min-max
|
|
54
|
+
module-header
|
|
55
|
+
move-zeroes
|
|
56
|
+
number-of-1-bits
|
|
57
|
+
number-of-steps
|
|
58
|
+
or-patterns
|
|
59
|
+
packet-router
|
|
60
|
+
parking-system
|
|
61
|
+
pipeline
|
|
62
|
+
pivot-index
|
|
63
|
+
plus-one
|
|
64
|
+
points
|
|
65
|
+
power-of-three
|
|
66
|
+
primes
|
|
67
|
+
raindrops
|
|
68
|
+
record
|
|
69
|
+
reverse-integer
|
|
70
|
+
roman-to-integer
|
|
71
|
+
ruby-eval
|
|
72
|
+
safe-lookup
|
|
73
|
+
scopes
|
|
74
|
+
shapes
|
|
75
|
+
single-number
|
|
76
|
+
squares
|
|
77
|
+
stack
|
|
78
|
+
subtract-product-sum
|
|
79
|
+
sum
|
|
80
|
+
thread-styles
|
|
81
|
+
threading
|
|
82
|
+
tic-tac-toe
|
|
83
|
+
tset
|
|
84
|
+
two-sum-hash
|
|
85
|
+
two-sum
|
|
86
|
+
ugly-number
|
|
87
|
+
underscore-patterns
|
|
88
|
+
valid-parentheses-1
|
|
89
|
+
zoo-animal-1
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
(local BIT-WIDTH 32)
|
|
2
|
+
|
|
3
|
+
(fn hamming-weight [n]
|
|
4
|
+
(var x n)
|
|
5
|
+
(var count 0)
|
|
6
|
+
(for [_ 1 BIT-WIDTH]
|
|
7
|
+
(set count (+ count (% x 2)))
|
|
8
|
+
(set x (: (/ x 2) :floor)))
|
|
9
|
+
count)
|
|
10
|
+
|
|
11
|
+
(print (hamming-weight 11))
|
|
12
|
+
(print (hamming-weight 128))
|
|
13
|
+
(print (hamming-weight 4294967293))
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
(local target 0)
|
|
2
|
+
|
|
3
|
+
(fn steps-to-zero [n]
|
|
4
|
+
(var x n)
|
|
5
|
+
(var steps 0)
|
|
6
|
+
(while (not= x target)
|
|
7
|
+
(if (= 0 (% x 2))
|
|
8
|
+
(set x (: (/ x 2) :floor))
|
|
9
|
+
(set x (- x 1)))
|
|
10
|
+
(set steps (+ steps 1)))
|
|
11
|
+
steps)
|
|
12
|
+
|
|
13
|
+
(print (steps-to-zero 14))
|
|
14
|
+
(print (steps-to-zero 8))
|
|
15
|
+
(print (steps-to-zero 123))
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
(class ParkingSystem)
|
|
2
|
+
|
|
3
|
+
(fn initialize [big medium small]
|
|
4
|
+
(set @big big)
|
|
5
|
+
(set @medium medium)
|
|
6
|
+
(set @small small))
|
|
7
|
+
|
|
8
|
+
(fn add-car [car-type]
|
|
9
|
+
(if (and (= car-type 1) (> @big 0)) (do (set @big (- @big 1)) true)
|
|
10
|
+
(and (= car-type 2) (> @medium 0)) (do (set @medium (- @medium 1)) true)
|
|
11
|
+
(and (= car-type 3) (> @small 0)) (do (set @small (- @small 1)) true)
|
|
12
|
+
false))
|
|
13
|
+
|
|
14
|
+
(let [parking (ParkingSystem.new 1 1 0)]
|
|
15
|
+
(print (parking.add-car 1))
|
|
16
|
+
(print (parking.add-car 2))
|
|
17
|
+
(print (parking.add-car 3))
|
|
18
|
+
(print (parking.add-car 1)))
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
(fn positive? [n] (> n 0))
|
|
2
|
+
(fn square [n] (* n n))
|
|
3
|
+
(fn add [x y] (+ x y))
|
|
4
|
+
(fn mul [x y] (* x y))
|
|
5
|
+
(fn nonzero [n] (if (= n 0) nil n))
|
|
6
|
+
(fn non-empty [s] (if (= s "") nil s))
|
|
7
|
+
(fn wrap [s] (.. ">>" s "<<"))
|
|
8
|
+
(fn shout [s] (.. s "!"))
|
|
9
|
+
|
|
10
|
+
(fn keep [pred xs]
|
|
11
|
+
(icollect [_ x (ipairs xs)]
|
|
12
|
+
(when (pred x) x)))
|
|
13
|
+
|
|
14
|
+
(fn map [f xs]
|
|
15
|
+
(icollect [_ x (ipairs xs)]
|
|
16
|
+
(f x)))
|
|
17
|
+
|
|
18
|
+
(fn join [sep xs]
|
|
19
|
+
(var s "")
|
|
20
|
+
(each [_ x (ipairs xs)]
|
|
21
|
+
(if (= s "")
|
|
22
|
+
(set s (.. x))
|
|
23
|
+
(set s (.. s sep x))))
|
|
24
|
+
s)
|
|
25
|
+
|
|
26
|
+
(let [scores [-2 3 -1 4 0 5]
|
|
27
|
+
report (->> scores
|
|
28
|
+
(keep positive?)
|
|
29
|
+
(map square)
|
|
30
|
+
(join ", "))
|
|
31
|
+
adjusted (-> 7 (add 3) (mul 2) (square))
|
|
32
|
+
ok (-?> "hello" (non-empty) (wrap) (shout))
|
|
33
|
+
bad (-?> "" (non-empty) (wrap) (shout))
|
|
34
|
+
live (-?>> 5 (nonzero) (mul 3) (add 1))
|
|
35
|
+
dead (-?>> 0 (nonzero) (mul 3) (add 1))]
|
|
36
|
+
(print report)
|
|
37
|
+
(print adjusted)
|
|
38
|
+
(print ok)
|
|
39
|
+
(print bad)
|
|
40
|
+
(print live)
|
|
41
|
+
(print dead))
|
data/examples/two-sum-hash.kap
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
(let [
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
(set i (+ i 1)))
|
|
13
|
-
answer)
|
|
14
|
-
]
|
|
1
|
+
(let [two-sum-hash (fn [nums target seen]
|
|
2
|
+
(var i 0)
|
|
3
|
+
(var answer nil)
|
|
4
|
+
(while (and (< i (length nums)) (= answer nil))
|
|
5
|
+
(let [n (. nums i)
|
|
6
|
+
complement (- target n)]
|
|
7
|
+
(if (seen.key? complement)
|
|
8
|
+
(set answer [(. seen complement) i])
|
|
9
|
+
(tset seen n i)))
|
|
10
|
+
(set i (+ i 1)))
|
|
11
|
+
answer)]
|
|
15
12
|
(print (two-sum-hash [2 7 11 15] 9 {}))
|
|
16
13
|
(print (two-sum-hash [3 2 4] 6 {}))
|
|
17
14
|
(print (two-sum-hash [1 2 3] 10 {})))
|
data/lib/kapusta/ast.rb
CHANGED
data/lib/kapusta/cli.rb
CHANGED
|
@@ -5,7 +5,7 @@ require 'optparse'
|
|
|
5
5
|
|
|
6
6
|
module Kapusta
|
|
7
7
|
class CLI
|
|
8
|
-
Options = Struct.new(:compile, :help, :version, keyword_init: true)
|
|
8
|
+
Options = Struct.new(:compile, :target, :help, :version, keyword_init: true)
|
|
9
9
|
|
|
10
10
|
def self.start(argv = ARGV)
|
|
11
11
|
args = argv.dup
|
|
@@ -21,8 +21,10 @@ module Kapusta
|
|
|
21
21
|
return
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
raise Kapusta::Error, Kapusta::Errors.format(:target_requires_compile) if options.target && !options.compile
|
|
25
|
+
|
|
24
26
|
if options.compile
|
|
25
|
-
compile_file(args)
|
|
27
|
+
compile_file(args, target: options.target)
|
|
26
28
|
else
|
|
27
29
|
run_file(args)
|
|
28
30
|
end
|
|
@@ -32,11 +34,14 @@ module Kapusta
|
|
|
32
34
|
end
|
|
33
35
|
|
|
34
36
|
def self.parse_options(args)
|
|
35
|
-
options = Options.new(compile: false, help: false, version: false)
|
|
37
|
+
options = Options.new(compile: false, target: nil, help: false, version: false)
|
|
36
38
|
|
|
37
39
|
OptionParser.new do |parser|
|
|
38
40
|
parser.banner = usage
|
|
39
41
|
parser.on('-c', '--compile', 'Compile .kap to Ruby') { options.compile = true }
|
|
42
|
+
parser.on('--target=TARGET', 'Compile for mruby') do |target|
|
|
43
|
+
options.target = Kapusta::Compiler.normalize_target(target)
|
|
44
|
+
end
|
|
40
45
|
parser.on('-h', '--help', 'Show this help') { options.help = true }
|
|
41
46
|
parser.on('-v', '--version', 'Show version') { options.version = true }
|
|
42
47
|
end.order!(args)
|
|
@@ -44,12 +49,12 @@ module Kapusta
|
|
|
44
49
|
options
|
|
45
50
|
end
|
|
46
51
|
|
|
47
|
-
def self.compile_file(args)
|
|
52
|
+
def self.compile_file(args, target:)
|
|
48
53
|
path = args.shift
|
|
49
54
|
abort usage unless path
|
|
50
55
|
abort usage unless args.empty?
|
|
51
56
|
|
|
52
|
-
$stdout.write(Kapusta.compile(File.read(path), path:))
|
|
57
|
+
$stdout.write(Kapusta.compile(File.read(path), path:, target:))
|
|
53
58
|
end
|
|
54
59
|
|
|
55
60
|
def self.run_file(args)
|
|
@@ -64,7 +69,7 @@ module Kapusta
|
|
|
64
69
|
end
|
|
65
70
|
|
|
66
71
|
def self.usage
|
|
67
|
-
'usage: kapusta [--compile|-c] <file.kap> | kapusta <file.kap> [args...]'
|
|
72
|
+
'usage: kapusta [--compile|-c] [--target=mruby] <file.kap> | kapusta <file.kap> [args...]'
|
|
68
73
|
end
|
|
69
74
|
end
|
|
70
75
|
end
|