Permalink
Browse files

initial import, kthnxbai.

  • Loading branch information...
0 parents commit 3e3a5ec663470e070283349f93731c4d6f16748d @igrigorik committed Dec 11, 2008
Showing with 299 additions and 0 deletions.
  1. +37 −0 README
  2. +187 −0 ruby2lolz.rb
  3. +47 −0 spec/lolz_spec.rb
  4. +8 −0 spec/specs/array.txt
  5. +5 −0 spec/specs/hash.txt
  6. +12 −0 spec/specs/hash_array.txt
  7. +3 −0 spec/specs/method.txt
37 README
@@ -0,0 +1,37 @@
+Ruby2Lolz translates Ruby code into LOLCODE (http://www.lolcode.com)
+
+For example:
+
+class Simple
+ def add(n1, n2)
+ return n1 + n2
+ end
+end
+
+Ruby2Lolz.translate(Simple, :add)
+
+HOW DUZ I HAZ add [YR n1, YR n2]
+ (n1 + n2)
+IF U SAY SO
+
+### OR ###
+
+> Ruby2Lolz.translate({:nickname => [:ig, :igrigorik]}.inspect)
+
+OH HAI
+ I CAN HAS Nickname
+ I CAN MANY HAZ
+ AWSUM VAR
+ ig
+ KTHNX.
+ AWSUM VAR
+ igrigorik
+ KTHNX.
+ KTHNXBYE.
+ KTHNX.
+KTHNXBYE.
+
+### OR ###
+
+Put some Lolz into your API!
+ - http://pastie.org/327494
@@ -0,0 +1,187 @@
+#!/usr/local/bin/ruby
+# Author: Ilya Grigorik (www.igvita.com)
+
+require "rubygems"
+require "parse_tree"
+require "parse_tree_extensions"
+require "unified_ruby"
+
+class Ruby2Lolz < SexpProcessor
+
+ def self.translate(klass_or_str, method = nil)
+ sexp = ParseTree.translate(klass_or_str, method)
+
+ # unified_ruby is a rewriter plugin that rewires
+ # the parse tree to make it easier to work with
+ # - defn arg above scope / making it arglist / ...
+ unifier = Unifier.new
+ unifier.processors.each do |p|
+ p.unsupported.delete :cfunc # HACK
+ end
+ sexp = unifier.process(sexp)
+
+ self.new.process(sexp)
+ end
+
+ def initialize
+ super
+ @indent = " "
+
+ self.auto_shift_type = true
+ self.strict = true
+ self.expected = String
+ end
+
+ ############################################################
+ # Processors
+
+ def process_lit(exp); exp.shift.to_s; end
+ def process_str(exp); exp.shift.to_s; end
+ def process_scope(exp); process(exp.shift); end
+ def process_lvar(exp); exp.shift.to_s; end
+
+
+ def process_arglist(exp, verbose = false)
+ code = []
+ until exp.empty? do
+ if verbose
+ code.push indent("AWSUM VAR\n #{indent(process(exp.shift))}\nKTHNX.")
+ else
+ code.push process(exp.shift)
+ end
+ end
+ code.join("\n")
+ end
+
+ def process_array(exp)
+ str = "I CAN MANY HAZ\n"
+ str << indent(process_arglist(exp, true))
+ str << "\nKTHNXBYE."
+ end
+
+ def process_hash(exp)
+ result = []
+
+ until exp.empty?
+ lhs = process(exp.shift)
+ rhs = exp.shift
+ t = rhs.first
+ rhs = process rhs
+ rhs = "#{rhs}" unless [:lit, :str].include? t # TODO: verify better!
+
+ result.push indent("I CAN HAS #{lhs.to_s.capitalize}\n #{indent(rhs)}\nKTHNX.")
+ end
+
+ case self.context[1]
+ when :arglist, :argscat then
+ return "#{result.join(', ')}"
+ else
+ return "OH HAI\n#{result.join("\n")}\nKTHNXBYE."
+ end
+ end
+
+ def process_defn(exp)
+ type1 = exp[1].first
+ type2 = exp[2].first rescue nil
+
+ case type1
+ when :scope, :args then
+ name = exp.shift
+ args = process(exp.shift)
+ args = "" if args == "[]"
+ body = indent(process(exp.shift))
+ return "HOW DUZ I HAZ #{name} [#{args}]\n#{body}\nIF U SAY SO"
+ else
+ raise "Unknown defn type: #{type1} for #{exp.inspect}"
+ end
+ end
+
+ def process_call(exp)
+ receiver_node_type = exp.first.nil? ? nil : exp.first.first
+ receiver = process exp.shift
+
+ name = exp.shift
+ args_exp = exp.shift rescue nil
+ if args_exp && args_exp.first == :array # FIX
+ args = "#{process(args_exp)[1..-2]}"
+ else
+ args = process args_exp
+ args = nil if args.empty?
+ end
+
+ case name
+ when :<=>, :==, :<, :>, :<=, :>=, :-, :+, :*, :/, :%, :<<, :>>, :** then
+ "(#{receiver} #{name} #{args})"
+ when :[] then
+ "#{receiver}[#{args}]"
+ when :"-@" then
+ "-#{receiver}"
+ when :"+@" then
+ "+#{receiver}"
+ else
+ unless receiver.nil? then
+ "#{receiver}.#{name}#{args ? "#{args})" : args}"
+ else
+ "#{name}#{args ? " #{args}" : args}"
+ end
+ end
+ end
+
+ def process_args(exp)
+ args = []
+
+ until exp.empty? do
+ arg = exp.shift
+ case arg
+ when Symbol then
+ args << "YR #{arg}"
+ when Array then
+ case arg.first
+ when :block then
+ asgns = {}
+ arg[1..-1].each do |lasgn|
+ asgns[lasgn[1]] = process(lasgn)
+ end
+
+ args.each_with_index do |name, index|
+ args[index] = asgns[name] if asgns.has_key? name
+ end
+ else
+ raise "unknown arg type #{arg.first.inspect}"
+ end
+ else
+ raise "unknown arg type #{arg.inspect}"
+ end
+ end
+
+ return "#{args.join ', '}"
+ end
+
+ def process_block(exp)
+ result = []
+ exp << nil if exp.empty?
+ until exp.empty? do
+ code = exp.shift
+
+ if code.nil? or code.first == :nil then
+ result << "# do nothing"
+ else
+ result << process(code)
+ end
+ end
+
+ result = result.join "\n"
+ result = case self.context[1]
+ when nil, :scope, :if, :iter, :resbody, :when, :while then
+ result + "\n"
+ else
+ "(#{result})"
+ end
+
+ return result
+ end
+
+ def indent(s)
+ s.to_s.split(/\n/).map{|line| @indent + line}.join("\n")
+ end
+end
@@ -0,0 +1,47 @@
+# LOLZ SPECS v1.2, KTHNXBAI.
+#
+# - http://lolcode.com/specs/1.2
+#
+
+require "rubygems"
+require "parse_tree"
+require "parse_tree_extensions"
+require "spec"
+require "ruby2lolz"
+
+def read_spec(name); File.open("spec/specs/#{name}.txt", "r").read.gsub("\r", ""); end
+
+describe Ruby2Lolz do
+
+ it "should translate Ruby hash to lolz, kthnx" do
+ h = {:user => "Ilya"}.inspect
+ Ruby2Lolz.translate(h).should == read_spec("hash")
+ end
+
+ it "should translate Ruby array to lolz, kthnx" do
+ a = ["igrigorik", "ig"].inspect
+ Ruby2Lolz.translate(a).should == read_spec("array")
+ end
+
+ it "should translate mixed Ruby array/hash to lolz, kthnx" do
+ h = {:nickname => ["igrigorik", "ig"]}.inspect
+ Ruby2Lolz.translate(h).should == read_spec("hash_array")
+ end
+
+ it "should translate Ruby method to lolz, kthnx" do
+ # [:defn,
+ # :hello,
+ # [:scope, [:block, [:args, :str], [:fcall, :puts, [:array, [:lvar, :str]]]]]]
+ class Simple
+ def hello(str); puts str; end;
+ end
+
+ Ruby2Lolz.translate(Simple, :hello).should == read_spec("method")
+ end
+
+ # it "should translate Ruby block to lolz, kthnx" do
+ # b = Proc.new {|var| puts var }.to_ruby
+ # puts Ruby2Lolz.translate(b)
+ # Ruby2Lolz.translate(b).should == read_spec("block")
+ # end
+end
@@ -0,0 +1,8 @@
+I CAN MANY HAZ
+ AWSUM VAR
+ igrigorik
+ KTHNX.
+ AWSUM VAR
+ ig
+ KTHNX.
+KTHNXBYE.
@@ -0,0 +1,5 @@
+OH HAI
+ I CAN HAS User
+ Ilya
+ KTHNX.
+KTHNXBYE.
@@ -0,0 +1,12 @@
+OH HAI
+ I CAN HAS Nickname
+ I CAN MANY HAZ
+ AWSUM VAR
+ igrigorik
+ KTHNX.
+ AWSUM VAR
+ ig
+ KTHNX.
+ KTHNXBYE.
+ KTHNX.
+KTHNXBYE.
@@ -0,0 +1,3 @@
+HOW DUZ I HAZ hello [YR str]
+ puts str
+IF U SAY SO

3 comments on commit 3e3a5ec

OHAI!

Can has COPYING or iz c no touch?

gf3 replied Dec 11, 2008

LOL! THX!

Please sign in to comment.