rampi 0.1.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 +7 -0
- data/.gitignore +8 -0
- data/.travis.yml +5 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +28 -0
- data/README.md +60 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/rampi +44 -0
- data/bin/setup +8 -0
- data/lib/rampi.rb +5 -0
- data/lib/rampi/code.rb +28 -0
- data/lib/rampi/compiler.rb +38 -0
- data/lib/rampi/core_ext.rb +1 -0
- data/lib/rampi/core_ext/numeric.rb +45 -0
- data/lib/rampi/dsl.rb +93 -0
- data/lib/rampi/functions.rb +200 -0
- data/lib/rampi/helpers.rb +21 -0
- data/lib/rampi/node.rb +99 -0
- data/lib/rampi/repl.rb +62 -0
- data/lib/rampi/variables.rb +17 -0
- data/lib/rampi/version.rb +3 -0
- data/rampi.gemspec +28 -0
- metadata +122 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 79a0034309690b38191031b4d0ddc9e1edb5862fdaa71424dea1f67ff23a9c39
|
4
|
+
data.tar.gz: e56ddc5c1d2dc065fa1667ecb07a4a4eb77c6ab6ec32e889d1a7d2037afe8291
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 05d710cc530fbefd8b0972869059777e8e50d102afa933bffb7e1d925a47b11418e7edd5b342b57500e764686bde52b3fc942d91ed8a390016adb214f0ed44b9
|
7
|
+
data.tar.gz: cd6202590df908b5f865b5f1cc1ca65f1efe65a70121115262aa31a7a90eb87c5f3c25ac68a956268349a42625b7dd5af5d238d389dbba74a2a3dd6e5250e633
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
rampi (0.1.0)
|
5
|
+
pry
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
coderay (1.1.2)
|
11
|
+
method_source (0.9.0)
|
12
|
+
minitest (5.11.3)
|
13
|
+
pry (0.11.3)
|
14
|
+
coderay (~> 1.1.0)
|
15
|
+
method_source (~> 0.9.0)
|
16
|
+
rake (10.5.0)
|
17
|
+
|
18
|
+
PLATFORMS
|
19
|
+
ruby
|
20
|
+
|
21
|
+
DEPENDENCIES
|
22
|
+
bundler (~> 1.16)
|
23
|
+
minitest (~> 5.0)
|
24
|
+
rake (~> 10.0)
|
25
|
+
rampi!
|
26
|
+
|
27
|
+
BUNDLED WITH
|
28
|
+
1.16.2
|
data/README.md
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# Rampi
|
2
|
+
|
3
|
+
Rampi is a REPL for [Rampcode](https://github.com/gabochi/rampclon), a bytecode
|
4
|
+
interpreter for Puredata. Rampi allows you to extend rampcode's minimalistic
|
5
|
+
language *on-the-fly*.
|
6
|
+
|
7
|
+
|
8
|
+
## Dependencies
|
9
|
+
|
10
|
+
* Ruby 2.3+
|
11
|
+
* Bundler
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
Run the following to install Rampi
|
16
|
+
|
17
|
+
$ gem install rampi
|
18
|
+
|
19
|
+
### Manual installation
|
20
|
+
|
21
|
+
1. Make sure Bundler is installed: `gem install bundler`.
|
22
|
+
2. Clone this repository and run `bin/setup` to install any dependencies.
|
23
|
+
3. Run `bundle exec rake install` to install Rampi.
|
24
|
+
|
25
|
+
|
26
|
+
## Editor integration
|
27
|
+
|
28
|
+
### Vim
|
29
|
+
|
30
|
+
Add the following line on your `~/.vimrc` file:
|
31
|
+
|
32
|
+
```
|
33
|
+
autocmd BufWritePost *.rampi silent exec "!rampi -f <afile>"
|
34
|
+
autocmd BufNewFile,BufRead *.rampi set syntax=ruby
|
35
|
+
```
|
36
|
+
|
37
|
+
## Usage
|
38
|
+
|
39
|
+
Start Puredata and load the rampcode patch. Then on a terminal run `rampi`
|
40
|
+
Use `r` and `c1`, `c2`, etc. to set ramp velocity and code lines.
|
41
|
+
|
42
|
+
|
43
|
+
## Development
|
44
|
+
|
45
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
46
|
+
`rake test` to run the tests. You can also run `bin/console` for an interactive
|
47
|
+
prompt that will allow you to experiment.
|
48
|
+
|
49
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
50
|
+
|
51
|
+
To release a new version, update the version number in `version.rb`, and then
|
52
|
+
run `bundle exec rake release`, which will create a git tag for the version,
|
53
|
+
push git commits and tags, and push the `.gem` file to
|
54
|
+
[rubygems.org](https://rubygems.org).
|
55
|
+
|
56
|
+
|
57
|
+
## Contributing
|
58
|
+
|
59
|
+
Bug reports and pull requests are welcome on GitHub at
|
60
|
+
https://github.com/munshkr/rampi.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "rampi"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/rampi
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rampi'
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
options = {:name => nil, :age => nil}
|
6
|
+
|
7
|
+
parser = OptionParser.new do|opts|
|
8
|
+
opts.banner = "Usage: rampi [options]"
|
9
|
+
|
10
|
+
opts.on('-f', '--file FILE', 'Evaluate the contenst of a file') do |path|
|
11
|
+
options[:file] = path
|
12
|
+
end
|
13
|
+
|
14
|
+
opts.on('-e', '--eval CODE', 'Evaluate inline code') do |code|
|
15
|
+
options[:eval] = code
|
16
|
+
end
|
17
|
+
|
18
|
+
opts.on('-p', '--port PORT', 'Connect to a different port (default: 3005)') do |port|
|
19
|
+
options[:port] = port.to_i
|
20
|
+
end
|
21
|
+
|
22
|
+
opts.on('-h', '--help', 'Display this message') do
|
23
|
+
puts opts
|
24
|
+
exit
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
parser.parse!
|
29
|
+
|
30
|
+
if options[:file] || options[:eval]
|
31
|
+
require 'rampi/code'
|
32
|
+
|
33
|
+
if options[:file]
|
34
|
+
code = Rampi::Code.from_file(options[:file], port: options[:port])
|
35
|
+
code.eval
|
36
|
+
else
|
37
|
+
code = Rampi::Code.new(options[:eval], port: options[:port])
|
38
|
+
code.eval
|
39
|
+
end
|
40
|
+
else
|
41
|
+
require 'rampi/repl'
|
42
|
+
|
43
|
+
Rampi::REPL.start(port: options[:port])
|
44
|
+
end
|
data/bin/setup
ADDED
data/lib/rampi.rb
ADDED
data/lib/rampi/code.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module Rampi
|
2
|
+
class Code
|
3
|
+
def self.from_file(path, port: nil)
|
4
|
+
new(File.read(path), filename: path, port: port)
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize(rampi_source, filename: '(rampi)', lineno: 1, port: nil)
|
8
|
+
@port = port
|
9
|
+
@block = CleanBinding.get.eval(<<-END_SOURCE, filename, lineno-1)
|
10
|
+
Proc.new do
|
11
|
+
#{rampi_source}
|
12
|
+
end
|
13
|
+
END_SOURCE
|
14
|
+
end
|
15
|
+
|
16
|
+
def eval
|
17
|
+
dsl = DSL.new(port: @port, autosync: false)
|
18
|
+
dsl.instance_eval(&@block)
|
19
|
+
dsl.sync!
|
20
|
+
end
|
21
|
+
|
22
|
+
module CleanBinding
|
23
|
+
def self.get
|
24
|
+
binding
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class Compiler
|
2
|
+
def compile(ramp:, code:)
|
3
|
+
code_body = code.map { |num, code_line|
|
4
|
+
code_line.map { |v| v && try(v) }.reject(&:nil?).join(' ')
|
5
|
+
}.join(', ')
|
6
|
+
|
7
|
+
"r #{ramp};\n" \
|
8
|
+
"#{ code_body.empty? ? '' : "c #{code_body};\n"}"
|
9
|
+
end
|
10
|
+
|
11
|
+
def visit_func(n)
|
12
|
+
"#{n.name}(#{n.args.map { |arg| try(arg) }.join('\,')})"
|
13
|
+
end
|
14
|
+
|
15
|
+
def visit_var(n)
|
16
|
+
case n.name
|
17
|
+
when :v1 then "$v1"
|
18
|
+
when :v2 then "$v2"
|
19
|
+
else n.name.to_s
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def visit_unary_expr(n)
|
24
|
+
"#{n.op}#{try(n.value)}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def visit_binary_expr(n)
|
28
|
+
"(#{try(n.left)}#{n.op}#{try(n.right)})"
|
29
|
+
end
|
30
|
+
|
31
|
+
def try(node_or_value)
|
32
|
+
if node_or_value.respond_to?(:accept)
|
33
|
+
node_or_value.accept(self)
|
34
|
+
else
|
35
|
+
node_or_value
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'rampi/core_ext/numeric'
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Rampi
|
2
|
+
module CoreExt
|
3
|
+
module Numeric
|
4
|
+
def +(o); o.is_a?(Node) ? BinaryExpr.new(:+, self, o) : super(o); end
|
5
|
+
def -(o); o.is_a?(Node) ? BinaryExpr.new(:-, self, o) : super(o); end
|
6
|
+
def *(o); o.is_a?(Node) ? BinaryExpr.new(:*, self, o) : super(o); end
|
7
|
+
def /(o); o.is_a?(Node) ? BinaryExpr.new(:/, self, o) : super(o); end
|
8
|
+
def %(o); o.is_a?(Node) ? BinaryExpr.new(:%, self, o) : super(o); end
|
9
|
+
def **(o); o.is_a?(Node) ? BinaryExpr.new(:**, self, o) : super(o); end
|
10
|
+
def >>(o); o.is_a?(Node) ? BinaryExpr.new(:>>, self, o) : super(o); end
|
11
|
+
def <<(o); o.is_a?(Node) ? BinaryExpr.new(:<<, self, o) : super(o); end
|
12
|
+
def <(o); o.is_a?(Node) ? BinaryExpr.new(:<, self, o) : super(o); end
|
13
|
+
def <=(o); o.is_a?(Node) ? BinaryExpr.new(:<=, self, o) : super(o); end
|
14
|
+
def >(o); o.is_a?(Node) ? BinaryExpr.new(:>, self, o) : super(o); end
|
15
|
+
def >=(o); o.is_a?(Node) ? BinaryExpr.new(:>=, self, o) : super(o); end
|
16
|
+
def ==(o); o.is_a?(Node) ? BinaryExpr.new(:==, self, o) : super(o); end
|
17
|
+
def !=(o); o.is_a?(Node) ? BinaryExpr.new(:!=, self, o) : super(o); end
|
18
|
+
def &(o); o.is_a?(Node) ? BinaryExpr.new(:&, self, o) : super(o); end
|
19
|
+
def ^(o); o.is_a?(Node) ? BinaryExpr.new(:^, self, o) : super(o); end
|
20
|
+
def |(o); o.is_a?(Node) ? BinaryExpr.new(:|, self, o) : super(o); end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Float
|
26
|
+
prepend Rampi::CoreExt::Numeric
|
27
|
+
end
|
28
|
+
|
29
|
+
class Rational
|
30
|
+
prepend Rampi::CoreExt::Numeric
|
31
|
+
end
|
32
|
+
|
33
|
+
if RUBY_VERSION.to_f >= 2.4
|
34
|
+
class Integer
|
35
|
+
prepend Rampi::CoreExt::Numeric
|
36
|
+
end
|
37
|
+
else
|
38
|
+
class Fixnum
|
39
|
+
prepend Rampi::CoreExt::Numeric
|
40
|
+
end
|
41
|
+
|
42
|
+
class Bignum
|
43
|
+
prepend Rampi::CoreExt::Numeric
|
44
|
+
end
|
45
|
+
end
|
data/lib/rampi/dsl.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'rampi/node'
|
2
|
+
require 'rampi/functions'
|
3
|
+
require 'rampi/compiler'
|
4
|
+
require 'rampi/helpers'
|
5
|
+
require 'rampi/core_ext'
|
6
|
+
require 'open3'
|
7
|
+
|
8
|
+
module Rampi
|
9
|
+
class DSL
|
10
|
+
include Rampi::Variables
|
11
|
+
include Rampi::Functions
|
12
|
+
include Rampi::Helpers
|
13
|
+
|
14
|
+
def initialize(port: 3005, autosync: true)
|
15
|
+
@port = port
|
16
|
+
@autosync = autosync
|
17
|
+
@ramp ||= 1.0
|
18
|
+
@code ||= {}
|
19
|
+
end
|
20
|
+
|
21
|
+
# Set ramp speed of +value+
|
22
|
+
def ramp(value=nil)
|
23
|
+
if value
|
24
|
+
@ramp = value
|
25
|
+
sync
|
26
|
+
end
|
27
|
+
@ramp
|
28
|
+
end
|
29
|
+
|
30
|
+
# Set code line for channel +num+ with +synth+ and parameters
|
31
|
+
def code(num, synth, lpf=0, lpq=0, delay_ms=0, delay_feed=0, pan=0)
|
32
|
+
@code[num] = [synth, lpf, lpq, delay_ms, delay_feed, pan]
|
33
|
+
sync
|
34
|
+
@code[num]
|
35
|
+
end
|
36
|
+
|
37
|
+
# Silence everything!
|
38
|
+
def hush
|
39
|
+
@code = {}
|
40
|
+
sync
|
41
|
+
end
|
42
|
+
|
43
|
+
##
|
44
|
+
# Common aliases for functions and variables
|
45
|
+
#
|
46
|
+
|
47
|
+
# Generate code methods
|
48
|
+
9.times do |i|
|
49
|
+
define_method("c#{i+1}") do |synth, *args|
|
50
|
+
code(i+1, synth, *args)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Same as #ramp
|
55
|
+
alias_method :r, :ramp
|
56
|
+
# Same as #code(1, ...)
|
57
|
+
alias_method :c, :c1
|
58
|
+
# Same as v1
|
59
|
+
alias_method :t, :v1
|
60
|
+
# Same as v2
|
61
|
+
alias_method :x, :v2
|
62
|
+
# Same as min(x, y)
|
63
|
+
alias_method :m, :min
|
64
|
+
# Same as sin(x)
|
65
|
+
alias_method :s, :sin
|
66
|
+
# Same as pow(x, y)
|
67
|
+
alias_method :p, :pow
|
68
|
+
# Same as step(x)
|
69
|
+
alias_method :q, :step
|
70
|
+
# Same as expe(x)
|
71
|
+
alias_method :f, :expe
|
72
|
+
# Same as invexpe(x)
|
73
|
+
alias_method :i, :invexpe
|
74
|
+
|
75
|
+
def sync
|
76
|
+
sync! if @autosync
|
77
|
+
end
|
78
|
+
|
79
|
+
def sync!
|
80
|
+
Open3.popen3("pdsend #{@port}") do |i, o, e, t|
|
81
|
+
i.write compile
|
82
|
+
i.close
|
83
|
+
res = o.read
|
84
|
+
puts "pdsend: #{res}" if !res.empty?
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def compile
|
89
|
+
@compiler ||= Compiler.new
|
90
|
+
@compiler.compile(ramp: @ramp, code: @code)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
require 'rampi/node'
|
2
|
+
|
3
|
+
module Rampi
|
4
|
+
module Functions
|
5
|
+
##
|
6
|
+
# Main functions
|
7
|
+
#
|
8
|
+
|
9
|
+
# Conditional - if (condition, IfTrue-expr, IfFalse-expr)
|
10
|
+
def if(cond, true_exp, false_exp)
|
11
|
+
Func.new(:if, cond, true_exp, false_exp)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Convert to integer
|
15
|
+
def int(arg)
|
16
|
+
Func.new(:int, arg)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Round a float to a nearby integer
|
20
|
+
def rint(arg)
|
21
|
+
Func.new(:rint, arg)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Convert to float
|
25
|
+
def float(arg)
|
26
|
+
Func.new(:float, arg)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Absolute value (added in pd 0.3)
|
30
|
+
def abs(arg)
|
31
|
+
Func.new(:abs, arg)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Minimum value between +arg1+ and +arg2+
|
35
|
+
def min(arg1, arg2)
|
36
|
+
Func.new(:min, arg1, arg2)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Maximum value between +x+ and +y+
|
40
|
+
def max(arg1, arg2)
|
41
|
+
Func.new(:max, arg1, arg2)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Largest integral value not greater than argument (added in pd 0.4)
|
45
|
+
def floor(arg)
|
46
|
+
Func.new(:floor, arg)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Smallest integral value not less than argument (added in pd 0.4)
|
50
|
+
def ceil(arg)
|
51
|
+
Func.new(:ceil, arg)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Floating-point remainder function (added in pd 0.4)
|
55
|
+
def fmod(arg)
|
56
|
+
Func.new(:fmod, arg)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Get signed intergar value from floating point number(added in version 0.4)
|
60
|
+
def imodf(arg)
|
61
|
+
Func.new(:imodf, arg)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Get signed fractional value from floating-point number(added in version 0.4)
|
65
|
+
def modf(arg)
|
66
|
+
Func.new(:modf, arg)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Floating-point remainder function (added in versio n 0.4)
|
70
|
+
def drem(arg1, arg2)
|
71
|
+
Func.new(:drem, arg1, arg2)
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# Power functions
|
76
|
+
#
|
77
|
+
|
78
|
+
# Raise +arg1+ to the power of +arg2+
|
79
|
+
# @example pow(x, y) is x to the power of y
|
80
|
+
def pow(arg1, arg2)
|
81
|
+
Func.new(:pow, arg1, arg2)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Square root of +x+
|
85
|
+
def sqrt(arg1)
|
86
|
+
Func.new(:sqrt, arg1)
|
87
|
+
end
|
88
|
+
|
89
|
+
# e raised to the power of +arg+
|
90
|
+
# @example exp(5.2) is e raised to the power of 5.2
|
91
|
+
def exp(arg)
|
92
|
+
Func.new(:exp, arg)
|
93
|
+
end
|
94
|
+
|
95
|
+
# Natural log
|
96
|
+
def ln(arg)
|
97
|
+
Func.new(:ln, arg)
|
98
|
+
end
|
99
|
+
alias_method :log, :ln
|
100
|
+
|
101
|
+
# Log base 10
|
102
|
+
def log10(arg)
|
103
|
+
Func.new(:log10, arg)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Factorial of +arg+
|
107
|
+
def fact(arg)
|
108
|
+
Func.new(:fact, arg)
|
109
|
+
end
|
110
|
+
|
111
|
+
# Cube root (added in pd 0.4)
|
112
|
+
def cbrt(arg)
|
113
|
+
Func.new(:cbrt, arg)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Exponential minus 1 (added in pd 0.4)
|
117
|
+
def expm1(arg)
|
118
|
+
Func.new(:expm1, arg)
|
119
|
+
end
|
120
|
+
|
121
|
+
# Logarithm of 1 plus (added in pd 0.4)
|
122
|
+
def log1p(arg)
|
123
|
+
Func.new(:log1p, arg)
|
124
|
+
end
|
125
|
+
|
126
|
+
# Multiply floating-point number by integral power of 2 (added in pd 0.4)
|
127
|
+
def ldexp(arg)
|
128
|
+
Func.new(:ldexp, arg)
|
129
|
+
end
|
130
|
+
|
131
|
+
##
|
132
|
+
# Trigonometric functions
|
133
|
+
#
|
134
|
+
|
135
|
+
# Sine
|
136
|
+
def sin(arg)
|
137
|
+
Func.new(:sin, arg)
|
138
|
+
end
|
139
|
+
|
140
|
+
# Cosine
|
141
|
+
def cos(arg)
|
142
|
+
Func.new(:cos, arg)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Tangent
|
146
|
+
def tan(arg)
|
147
|
+
Func.new(:tan, arg)
|
148
|
+
end
|
149
|
+
|
150
|
+
# Arc sine
|
151
|
+
def asin(arg)
|
152
|
+
Func.new(:asin, arg)
|
153
|
+
end
|
154
|
+
|
155
|
+
# Arc cosine
|
156
|
+
def acos(arg)
|
157
|
+
Func.new(:acos, arg)
|
158
|
+
end
|
159
|
+
|
160
|
+
# Arc tangent
|
161
|
+
def atan(arg)
|
162
|
+
Func.new(:atan, arg)
|
163
|
+
end
|
164
|
+
|
165
|
+
# Arc tangent of 2 variables
|
166
|
+
def atan2(arg1, arg2)
|
167
|
+
Func.new(:atan2, arg1, arg2)
|
168
|
+
end
|
169
|
+
|
170
|
+
# Hyperbolic sine
|
171
|
+
def sinh()
|
172
|
+
Func.new(:sinh, arg)
|
173
|
+
end
|
174
|
+
|
175
|
+
# Hyperbolic cosine
|
176
|
+
def cosh()
|
177
|
+
Func.new(:cosh, arg)
|
178
|
+
end
|
179
|
+
|
180
|
+
# Hyperbolic tangent
|
181
|
+
def tanh()
|
182
|
+
Func.new(:tanh, arg)
|
183
|
+
end
|
184
|
+
|
185
|
+
# Inverse hyperbolic sine
|
186
|
+
def asinh()
|
187
|
+
Func.new(:asinh, arg)
|
188
|
+
end
|
189
|
+
|
190
|
+
# Inverse hyperbolic cosine
|
191
|
+
def acosh()
|
192
|
+
Func.new(:acosh, arg)
|
193
|
+
end
|
194
|
+
|
195
|
+
# Inverse hyperbolic tangent
|
196
|
+
def atanh()
|
197
|
+
Func.new(:atanh, arg)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rampi/node'
|
2
|
+
require 'rampi/variables'
|
3
|
+
|
4
|
+
module Rampi
|
5
|
+
module Helpers
|
6
|
+
# Step semiquaver counter
|
7
|
+
def step(value)
|
8
|
+
(v1 / 1000) % value
|
9
|
+
end
|
10
|
+
|
11
|
+
# Exponential envelope
|
12
|
+
def expe(value)
|
13
|
+
1 - pow((v1 % 1000) / 1000, value)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Inverse exponential envelope
|
17
|
+
def invexpe(value)
|
18
|
+
pow((v1 % 1000) / 1000, value)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/rampi/node.rb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
module Rampi
|
2
|
+
class Node
|
3
|
+
def +(rvalue); BinaryExpr.new(:+, self, rvalue); end
|
4
|
+
def -(rvalue); BinaryExpr.new(:-, self, rvalue) end
|
5
|
+
def *(rvalue); BinaryExpr.new(:*, self, rvalue); end
|
6
|
+
def /(rvalue); BinaryExpr.new(:/, self, rvalue); end
|
7
|
+
def %(rvalue); BinaryExpr.new(:%, self, rvalue); end
|
8
|
+
def **(rvalue); BinaryExpr.new(:**, self, rvalue); end
|
9
|
+
def >>(rvalue); BinaryExpr.new(:>>, self, rvalue); end
|
10
|
+
def <<(rvalue); BinaryExpr.new(:<<, self, rvalue); end
|
11
|
+
def <(rvalue); BinaryExpr.new(:<, self, rvalue); end
|
12
|
+
def <=(rvalue); BinaryExpr.new(:<=, self, rvalue); end
|
13
|
+
def >(rvalue); BinaryExpr.new(:>, self, rvalue); end
|
14
|
+
def >=(rvalue); BinaryExpr.new(:>=, self, rvalue); end
|
15
|
+
def ==(rvalue); BinaryExpr.new(:==, self, rvalue); end
|
16
|
+
def !=(rvalue); BinaryExpr.new(:!=, self, rvalue); end
|
17
|
+
def &(rvalue); BinaryExpr.new(:&, self, rvalue); end
|
18
|
+
def ^(rvalue); BinaryExpr.new(:^, self, rvalue); end
|
19
|
+
def |(rvalue); BinaryExpr.new(:|, self, rvalue); end
|
20
|
+
|
21
|
+
def -@; UnaryExpr.new(:-, self); end
|
22
|
+
def ~; UnaryExpr.new(:~, self); end
|
23
|
+
end
|
24
|
+
|
25
|
+
class BinaryExpr < Node
|
26
|
+
attr_accessor :op, :left, :right
|
27
|
+
|
28
|
+
def initialize(op, left, right)
|
29
|
+
@op = op
|
30
|
+
@left = left
|
31
|
+
@right = right
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_s
|
35
|
+
"(#{@left} #{@op} #{@right})"
|
36
|
+
end
|
37
|
+
alias_method :inspect, :to_s
|
38
|
+
|
39
|
+
def accept(visitor)
|
40
|
+
visitor.visit_binary_expr(self)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class UnaryExpr < Node
|
45
|
+
attr_accessor :op, :value
|
46
|
+
|
47
|
+
def initialize(op, value)
|
48
|
+
@op = op
|
49
|
+
@value = value
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_s
|
53
|
+
"#{@op}#{@value}"
|
54
|
+
end
|
55
|
+
alias_method :inspect, :to_s
|
56
|
+
|
57
|
+
def accept(visitor)
|
58
|
+
visitor.visit_unary_expr(self)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class Func < Node
|
63
|
+
attr_accessor :name, :args, :kwargs
|
64
|
+
|
65
|
+
def initialize(name, *args, **kwargs)
|
66
|
+
@name = name
|
67
|
+
@args = args
|
68
|
+
@kwargs = kwargs
|
69
|
+
end
|
70
|
+
|
71
|
+
def to_s
|
72
|
+
kwargs_s = @kwargs.map { |k, v| "#{k}: #{v}" }.join(', ')
|
73
|
+
args_s = @args.join(', ')
|
74
|
+
"#{@name}(#{args_s}#{!kwargs_s.empty? ? ", #{kwargs_s}" : ''})"
|
75
|
+
end
|
76
|
+
alias_method :inspect, :to_s
|
77
|
+
|
78
|
+
def accept(visitor)
|
79
|
+
visitor.visit_func(self)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class Var < Node
|
84
|
+
attr_accessor :name
|
85
|
+
|
86
|
+
def initialize(name)
|
87
|
+
@name = name
|
88
|
+
end
|
89
|
+
|
90
|
+
def to_s
|
91
|
+
name.to_s
|
92
|
+
end
|
93
|
+
alias_method :inspect, :to_s
|
94
|
+
|
95
|
+
def accept(visitor)
|
96
|
+
visitor.visit_var(self)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
data/lib/rampi/repl.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'pry'
|
2
|
+
require 'io/console'
|
3
|
+
|
4
|
+
module Rampi
|
5
|
+
module REPL
|
6
|
+
extend self
|
7
|
+
|
8
|
+
CONFIG_PATH = File.expand_path('~/.config/rampi')
|
9
|
+
HISTORY_FILE = 'history'
|
10
|
+
INIT_SCRIPT_FILE = 'init.rb'
|
11
|
+
|
12
|
+
DEFAULT_INIT_SCRIPT =
|
13
|
+
"# Here you can customize or define functions \n" \
|
14
|
+
"# that will be available in Rampi\n\n"
|
15
|
+
|
16
|
+
def start(port: nil)
|
17
|
+
configure
|
18
|
+
load_init_script
|
19
|
+
|
20
|
+
dsl = DSL.new(port: port)
|
21
|
+
dsl.pry
|
22
|
+
end
|
23
|
+
|
24
|
+
def configure
|
25
|
+
prepare_config_dir
|
26
|
+
|
27
|
+
if ENV['INSIDE_EMACS']
|
28
|
+
Pry.config.correct_indent = false
|
29
|
+
Pry.config.pager = false
|
30
|
+
Pry.config.prompt = [ proc { '' }, proc { '' }]
|
31
|
+
else
|
32
|
+
Pry.config.prompt = [ proc { '>> ' }, proc { '.> ' }]
|
33
|
+
end
|
34
|
+
|
35
|
+
Pry.config.history.file = history_path
|
36
|
+
end
|
37
|
+
|
38
|
+
def red(string)
|
39
|
+
"\e[31m\e[1m#{string}\e[22m\e[0m"
|
40
|
+
end
|
41
|
+
|
42
|
+
def load_init_script
|
43
|
+
require(init_script_path)
|
44
|
+
end
|
45
|
+
|
46
|
+
def prepare_config_dir
|
47
|
+
FileUtils.mkdir_p(CONFIG_PATH)
|
48
|
+
|
49
|
+
unless File.exists?(init_script_path)
|
50
|
+
File.write(init_script_path, DEFAULT_INIT_SCRIPT)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def history_path
|
55
|
+
File.join(CONFIG_PATH, HISTORY_FILE)
|
56
|
+
end
|
57
|
+
|
58
|
+
def init_script_path
|
59
|
+
File.join(CONFIG_PATH, INIT_SCRIPT_FILE)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rampi/node'
|
2
|
+
|
3
|
+
module Rampi
|
4
|
+
module Variables
|
5
|
+
# Time variable, actual value of the ramp
|
6
|
+
# +8000 per cycle
|
7
|
+
def v1
|
8
|
+
Var.new(:v1)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Random variable between 0 and 1
|
12
|
+
# Updated at every step
|
13
|
+
def v2
|
14
|
+
Var.new(:v2)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/rampi.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
lib = File.expand_path("../lib", __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "rampi/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "rampi"
|
7
|
+
spec.version = Rampi::VERSION
|
8
|
+
spec.authors = ["Damián Silvani"]
|
9
|
+
spec.email = ["munshkr@gmail.com"]
|
10
|
+
|
11
|
+
spec.summary = %q{REPL for Rampcode, a bytecode interpreter for Puredata}
|
12
|
+
spec.homepage = "https://github.com/munshkr/rampi"
|
13
|
+
|
14
|
+
# Specify which files should be added to the gem when it is released.
|
15
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
16
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
17
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
end
|
19
|
+
spec.bindir = "bin"
|
20
|
+
spec.executables = ["rampi"]
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_dependency "pry"
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.16"
|
26
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
27
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rampi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Damián Silvani
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-08-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: pry
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.16'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.16'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '5.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '5.0'
|
69
|
+
description:
|
70
|
+
email:
|
71
|
+
- munshkr@gmail.com
|
72
|
+
executables:
|
73
|
+
- rampi
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- ".gitignore"
|
78
|
+
- ".travis.yml"
|
79
|
+
- Gemfile
|
80
|
+
- Gemfile.lock
|
81
|
+
- README.md
|
82
|
+
- Rakefile
|
83
|
+
- bin/console
|
84
|
+
- bin/rampi
|
85
|
+
- bin/setup
|
86
|
+
- lib/rampi.rb
|
87
|
+
- lib/rampi/code.rb
|
88
|
+
- lib/rampi/compiler.rb
|
89
|
+
- lib/rampi/core_ext.rb
|
90
|
+
- lib/rampi/core_ext/numeric.rb
|
91
|
+
- lib/rampi/dsl.rb
|
92
|
+
- lib/rampi/functions.rb
|
93
|
+
- lib/rampi/helpers.rb
|
94
|
+
- lib/rampi/node.rb
|
95
|
+
- lib/rampi/repl.rb
|
96
|
+
- lib/rampi/variables.rb
|
97
|
+
- lib/rampi/version.rb
|
98
|
+
- rampi.gemspec
|
99
|
+
homepage: https://github.com/munshkr/rampi
|
100
|
+
licenses: []
|
101
|
+
metadata: {}
|
102
|
+
post_install_message:
|
103
|
+
rdoc_options: []
|
104
|
+
require_paths:
|
105
|
+
- lib
|
106
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - ">="
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0'
|
116
|
+
requirements: []
|
117
|
+
rubyforge_project:
|
118
|
+
rubygems_version: 2.7.6
|
119
|
+
signing_key:
|
120
|
+
specification_version: 4
|
121
|
+
summary: REPL for Rampcode, a bytecode interpreter for Puredata
|
122
|
+
test_files: []
|