ruby2lolz 0.0.1
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.
- data/README.rdoc +38 -0
- data/Rakefile +19 -0
- data/VERSION +1 -0
- data/lib/ruby2lolz.rb +195 -0
- data/spec/lolz_spec.rb +59 -0
- data/spec/specs/array.txt +8 -0
- data/spec/specs/hash.txt +5 -0
- data/spec/specs/hash_array.txt +12 -0
- data/spec/specs/method.txt +3 -0
- metadata +72 -0
data/README.rdoc
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
Ruby2Lolz translates Ruby code into LOLCODE (http://www.lolcode.com)
|
2
|
+
- http://www.igvita.com/2008/12/11/ruby-ast-for-fun-and-profit/
|
3
|
+
|
4
|
+
== Translating Ruby Hash & Array:
|
5
|
+
require 'ruby2lolz'
|
6
|
+
# adds Hash.to_lolz, and Array.to_lolz
|
7
|
+
|
8
|
+
puts {:nickname => [:ig, :igrigorik]}.to_lolz
|
9
|
+
|
10
|
+
OH HAI
|
11
|
+
I CAN HAS Nickname
|
12
|
+
I CAN MANY HAZ
|
13
|
+
AWSUM VAR
|
14
|
+
ig
|
15
|
+
KTHNX.
|
16
|
+
AWSUM VAR
|
17
|
+
igrigorik
|
18
|
+
KTHNX.
|
19
|
+
KTHNXBYE.
|
20
|
+
KTHNX.
|
21
|
+
KTHNXBYE.
|
22
|
+
|
23
|
+
Put some Lolz into your API
|
24
|
+
- http://pastie.org/327494
|
25
|
+
|
26
|
+
== Translating a class:
|
27
|
+
|
28
|
+
class Simple
|
29
|
+
def add(n1, n2)
|
30
|
+
return n1 + n2
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
Ruby2Lolz.translate(Simple, :add)
|
35
|
+
|
36
|
+
HOW DUZ I HAZ add [YR n1, YR n2]
|
37
|
+
(n1 + n2)
|
38
|
+
IF U SAY SO
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rake'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'jeweler'
|
5
|
+
Jeweler::Tasks.new do |gemspec|
|
6
|
+
gemspec.name = "ruby2lolz"
|
7
|
+
gemspec.summary = "Ruby to Lolcode translator, kthnxbai."
|
8
|
+
gemspec.description = gemspec.summary
|
9
|
+
gemspec.email = "ilya@igvita.com"
|
10
|
+
gemspec.homepage = "http://github.com/igrigorik/ruby2lolz"
|
11
|
+
gemspec.authors = ["Ilya Grigorik"]
|
12
|
+
gemspec.add_dependency('ParseTree')
|
13
|
+
gemspec.rubyforge_project = "ruby2lolz"
|
14
|
+
end
|
15
|
+
|
16
|
+
Jeweler::GemcutterTasks.new
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
19
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/lib/ruby2lolz.rb
ADDED
@@ -0,0 +1,195 @@
|
|
1
|
+
#!/usr/local/bin/ruby
|
2
|
+
# Author: Ilya Grigorik (www.igvita.com)
|
3
|
+
|
4
|
+
require "rubygems"
|
5
|
+
require "parse_tree"
|
6
|
+
require "parse_tree_extensions"
|
7
|
+
require "unified_ruby"
|
8
|
+
|
9
|
+
class Hash
|
10
|
+
def to_lolz; Ruby2Lolz.translate(self.inspect); end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Array
|
14
|
+
def to_lolz; Ruby2Lolz.translate(self.inspect); end
|
15
|
+
end
|
16
|
+
|
17
|
+
class Ruby2Lolz < SexpProcessor
|
18
|
+
|
19
|
+
def self.translate(klass_or_str, method = nil)
|
20
|
+
sexp = ParseTree.translate(klass_or_str, method)
|
21
|
+
|
22
|
+
# unified_ruby is a rewriter plugin that rewires
|
23
|
+
# the parse tree to make it easier to work with
|
24
|
+
# - defn arg above scope / making it arglist / ...
|
25
|
+
unifier = Unifier.new
|
26
|
+
unifier.processors.each do |p|
|
27
|
+
p.unsupported.delete :cfunc # HACK
|
28
|
+
end
|
29
|
+
sexp = unifier.process(sexp)
|
30
|
+
|
31
|
+
self.new.process(sexp)
|
32
|
+
end
|
33
|
+
|
34
|
+
def initialize
|
35
|
+
super
|
36
|
+
@indent = " "
|
37
|
+
|
38
|
+
self.auto_shift_type = true
|
39
|
+
self.strict = true
|
40
|
+
self.expected = String
|
41
|
+
end
|
42
|
+
|
43
|
+
############################################################
|
44
|
+
# Processors
|
45
|
+
|
46
|
+
def process_lit(exp); exp.shift.to_s; end
|
47
|
+
def process_str(exp); exp.shift.to_s; end
|
48
|
+
def process_scope(exp); process(exp.shift); end
|
49
|
+
def process_lvar(exp); exp.shift.to_s; end
|
50
|
+
|
51
|
+
|
52
|
+
def process_arglist(exp, verbose = false)
|
53
|
+
code = []
|
54
|
+
until exp.empty? do
|
55
|
+
if verbose
|
56
|
+
code.push indent("AWSUM VAR\n #{indent(process(exp.shift))}\nKTHNX.")
|
57
|
+
else
|
58
|
+
code.push process(exp.shift)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
code.join("\n")
|
62
|
+
end
|
63
|
+
|
64
|
+
def process_array(exp)
|
65
|
+
str = "I CAN MANY HAZ\n"
|
66
|
+
str << indent(process_arglist(exp, true))
|
67
|
+
str << "\nKTHNXBYE."
|
68
|
+
end
|
69
|
+
|
70
|
+
def process_hash(exp)
|
71
|
+
result = []
|
72
|
+
|
73
|
+
until exp.empty?
|
74
|
+
lhs = process(exp.shift)
|
75
|
+
rhs = exp.shift
|
76
|
+
t = rhs.first
|
77
|
+
rhs = process rhs
|
78
|
+
rhs = "#{rhs}" unless [:lit, :str].include? t # TODO: verify better!
|
79
|
+
|
80
|
+
result.push indent("I CAN HAS #{lhs.to_s.capitalize}\n #{indent(rhs)}\nKTHNX.")
|
81
|
+
end
|
82
|
+
|
83
|
+
case self.context[1]
|
84
|
+
when :arglist, :argscat then
|
85
|
+
return "#{result.join(', ')}"
|
86
|
+
else
|
87
|
+
return "OH HAI\n#{result.join("\n")}\nKTHNXBYE."
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def process_defn(exp)
|
92
|
+
type1 = exp[1].first
|
93
|
+
type2 = exp[2].first rescue nil
|
94
|
+
|
95
|
+
case type1
|
96
|
+
when :scope, :args then
|
97
|
+
name = exp.shift
|
98
|
+
args = process(exp.shift)
|
99
|
+
args = "" if args == "[]"
|
100
|
+
body = indent(process(exp.shift))
|
101
|
+
return "HOW DUZ I HAZ #{name} [#{args}]\n#{body}\nIF U SAY SO"
|
102
|
+
else
|
103
|
+
raise "Unknown defn type: #{type1} for #{exp.inspect}"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def process_call(exp)
|
108
|
+
receiver_node_type = exp.first.nil? ? nil : exp.first.first
|
109
|
+
receiver = process exp.shift
|
110
|
+
|
111
|
+
name = exp.shift
|
112
|
+
args_exp = exp.shift rescue nil
|
113
|
+
if args_exp && args_exp.first == :array # FIX
|
114
|
+
args = "#{process(args_exp)[1..-2]}"
|
115
|
+
else
|
116
|
+
args = process args_exp
|
117
|
+
args = nil if args.empty?
|
118
|
+
end
|
119
|
+
|
120
|
+
case name
|
121
|
+
when :<=>, :==, :<, :>, :<=, :>=, :-, :+, :*, :/, :%, :<<, :>>, :** then
|
122
|
+
"(#{receiver} #{name} #{args})"
|
123
|
+
when :[] then
|
124
|
+
"#{receiver}[#{args}]"
|
125
|
+
when :"-@" then
|
126
|
+
"-#{receiver}"
|
127
|
+
when :"+@" then
|
128
|
+
"+#{receiver}"
|
129
|
+
else
|
130
|
+
unless receiver.nil? then
|
131
|
+
"#{receiver}.#{name}#{args ? "#{args})" : args}"
|
132
|
+
else
|
133
|
+
"#{name}#{args ? " #{args}" : args}"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def process_args(exp)
|
139
|
+
args = []
|
140
|
+
|
141
|
+
until exp.empty? do
|
142
|
+
arg = exp.shift
|
143
|
+
case arg
|
144
|
+
when Symbol then
|
145
|
+
args << "YR #{arg}"
|
146
|
+
when Array then
|
147
|
+
case arg.first
|
148
|
+
when :block then
|
149
|
+
asgns = {}
|
150
|
+
arg[1..-1].each do |lasgn|
|
151
|
+
asgns[lasgn[1]] = process(lasgn)
|
152
|
+
end
|
153
|
+
|
154
|
+
args.each_with_index do |name, index|
|
155
|
+
args[index] = asgns[name] if asgns.has_key? name
|
156
|
+
end
|
157
|
+
else
|
158
|
+
raise "unknown arg type #{arg.first.inspect}"
|
159
|
+
end
|
160
|
+
else
|
161
|
+
raise "unknown arg type #{arg.inspect}"
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
return "#{args.join ', '}"
|
166
|
+
end
|
167
|
+
|
168
|
+
def process_block(exp)
|
169
|
+
result = []
|
170
|
+
exp << nil if exp.empty?
|
171
|
+
until exp.empty? do
|
172
|
+
code = exp.shift
|
173
|
+
|
174
|
+
if code.nil? or code.first == :nil then
|
175
|
+
result << "# do nothing"
|
176
|
+
else
|
177
|
+
result << process(code)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
result = result.join "\n"
|
182
|
+
result = case self.context[1]
|
183
|
+
when nil, :scope, :if, :iter, :resbody, :when, :while then
|
184
|
+
result + "\n"
|
185
|
+
else
|
186
|
+
"(#{result})"
|
187
|
+
end
|
188
|
+
|
189
|
+
return result
|
190
|
+
end
|
191
|
+
|
192
|
+
def indent(s)
|
193
|
+
s.to_s.split(/\n/).map{|line| @indent + line}.join("\n")
|
194
|
+
end
|
195
|
+
end
|
data/spec/lolz_spec.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# LOLZ SPECS v1.2, KTHNXBAI.
|
2
|
+
#
|
3
|
+
# - http://lolcode.com/specs/1.2
|
4
|
+
#
|
5
|
+
|
6
|
+
require "rubygems"
|
7
|
+
require "parse_tree"
|
8
|
+
require "parse_tree_extensions"
|
9
|
+
require "spec"
|
10
|
+
require "ruby2lolz"
|
11
|
+
|
12
|
+
def read_spec(name); File.open("spec/specs/#{name}.txt", "r").read.gsub("\r", ""); end
|
13
|
+
|
14
|
+
describe Ruby2Lolz do
|
15
|
+
|
16
|
+
it "should translate Ruby hash to lolz, kthnx" do
|
17
|
+
h = {:user => "Ilya"}.inspect
|
18
|
+
Ruby2Lolz.translate(h).should == read_spec("hash")
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should translate Ruby hash to lolz, kthnx" do
|
22
|
+
{:user => "Ilya"}.to_lolz.should == read_spec("hash")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should translate Ruby array to lolz, kthnx" do
|
26
|
+
a = ["igrigorik", "ig"].inspect
|
27
|
+
Ruby2Lolz.translate(a).should == read_spec("array")
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should translate Ruby array to lolz, kthnx" do
|
31
|
+
["igrigorik", "ig"].to_lolz.should == read_spec("array")
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should translate mixed Ruby array/hash to lolz, kthnx" do
|
35
|
+
h = {:nickname => ["igrigorik", "ig"]}.inspect
|
36
|
+
Ruby2Lolz.translate(h).should == read_spec("hash_array")
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should translate mixed Ruby array/hash to lolz, kthnx" do
|
40
|
+
{:nickname => ["igrigorik", "ig"]}.to_lolz.should == read_spec("hash_array")
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should translate Ruby method to lolz, kthnx" do
|
44
|
+
# [:defn,
|
45
|
+
# :hello,
|
46
|
+
# [:scope, [:block, [:args, :str], [:fcall, :puts, [:array, [:lvar, :str]]]]]]
|
47
|
+
class Simple
|
48
|
+
def hello(str); puts str; end;
|
49
|
+
end
|
50
|
+
|
51
|
+
Ruby2Lolz.translate(Simple, :hello).should == read_spec("method")
|
52
|
+
end
|
53
|
+
|
54
|
+
# it "should translate Ruby block to lolz, kthnx" do
|
55
|
+
# b = Proc.new {|var| puts var }.to_ruby
|
56
|
+
# puts Ruby2Lolz.translate(b)
|
57
|
+
# Ruby2Lolz.translate(b).should == read_spec("block")
|
58
|
+
# end
|
59
|
+
end
|
data/spec/specs/hash.txt
ADDED
metadata
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruby2lolz
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ilya Grigorik
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-12-12 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: ParseTree
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
description: Ruby to Lolcode translator, kthnxbai.
|
26
|
+
email: ilya@igvita.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- README.rdoc
|
33
|
+
files:
|
34
|
+
- README.rdoc
|
35
|
+
- Rakefile
|
36
|
+
- VERSION
|
37
|
+
- lib/ruby2lolz.rb
|
38
|
+
- spec/lolz_spec.rb
|
39
|
+
- spec/specs/array.txt
|
40
|
+
- spec/specs/hash.txt
|
41
|
+
- spec/specs/hash_array.txt
|
42
|
+
- spec/specs/method.txt
|
43
|
+
has_rdoc: true
|
44
|
+
homepage: http://github.com/igrigorik/ruby2lolz
|
45
|
+
licenses: []
|
46
|
+
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options:
|
49
|
+
- --charset=UTF-8
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: "0"
|
57
|
+
version:
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: "0"
|
63
|
+
version:
|
64
|
+
requirements: []
|
65
|
+
|
66
|
+
rubyforge_project: ruby2lolz
|
67
|
+
rubygems_version: 1.3.5
|
68
|
+
signing_key:
|
69
|
+
specification_version: 3
|
70
|
+
summary: Ruby to Lolcode translator, kthnxbai.
|
71
|
+
test_files:
|
72
|
+
- spec/lolz_spec.rb
|