ruby2lolz 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|