Created
April 1, 2010 11:09
-
-
Save faultier/351671 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# vim: fileencoding=utf-8 filetype=ruby | |
require 'rack' | |
require 'stringio' | |
require 'ruby2ruby' | |
require 'esoteric/dt' | |
module Esoteric | |
module DT | |
class Server | |
def initialize(dir='handler') | |
@processor = Ruby2Ruby.new | |
@handlers = {} | |
@base_dir = dir | |
end | |
def call(env) | |
req = Rack::Request.new(env) | |
status = 200 | |
body = '' | |
headers = { 'content-type' => 'text/plain' } | |
buffer = StringIO.new | |
begin | |
input = req['rack.input'].nil? ? StringIO.new(req.query_string) : req['rack.input'] | |
exit_code = handler(req.path, req.params).call(input, buffer) | |
raise "DT error: (exit code=#{exit_code})" if exit_code != 0 | |
body = buffer.string | |
buffer.close | |
if body =~ /^((?:(?:[\w\-]+: [^\n]+)\n)+)\n(.+)$/im | |
body = $2 | |
header = $1 | |
header.each_line {|line| headers[$1.downcase] = $2 if line =~ /\A([\w\-]+): (.+)\n?\z/} | |
end | |
rescue | |
warn $! | |
status = 500 | |
body = 'Internal Server Error' | |
end | |
res = Rack::Response.new {|r| | |
r.status = status | |
headers.each_pair {|key,val| r[key] = val } | |
r.write body | |
} | |
res.finish | |
end | |
private | |
def ast_normalize(ast) | |
if (ast.kind_of?(Array)) | |
case ast[0] | |
when :gasgn | |
lvar_name = case ast[1] | |
when :$stack then :_s | |
when :$heap then nil | |
else ast[1].to_s.sub('$','').intern end | |
[:lasgn, lvar_name, ast_normalize(ast[2])] if lvar_name | |
when :gvar | |
ast[0] = :lvar | |
ast[1] = case ast[1] | |
when :$stack then :_s | |
when :$heap then :_h | |
when :$stdin then :_i | |
when :$stdout then :_o | |
else ast[1].to_s.sub('$','').intern end | |
ast | |
when :call | |
ast[2] = :return if ast[2] == :exit | |
[ast[0]] + ast[1..ast.size-1].map{|exp|ast_normalize(exp)} | |
when :arglist, :block | |
[ast[0]] + ast[1..ast.size-1].map{|exp|ast_normalize(exp)} | |
else | |
ast | |
end | |
else | |
ast | |
end | |
end | |
def params_normalize(params) | |
n_params = {} | |
params.each_pair do |key,val| | |
next unless key.kind_of?(String) && key.length == 1 | |
case val | |
when /\A\d+\z/ | |
n_params[key.ord] = val.to_i | |
when /\A[a-zA-Z]\z/ | |
n_params[key.ord] = val.ord | |
end | |
end | |
n_params | |
end | |
def handler(path, params={}) | |
file = @base_dir + path | |
file = file + 'index.dt' if file =~ /\/\z/ | |
file = file + '.dt' unless file =~ /\.dt\z/ | |
params = params_normalize(params) | |
handler = @handlers[file] | |
unless handler && handler.kind_of?(Proc) | |
ast = ast_normalize(::Esoteric::DT::Parser.parse(::File.read(file))).compact | |
ast.push [:call, nil, :return, [:arglist, [:lit, 0]]] unless ast.last[0] == :call && ast.last[2] == :return | |
sexp = Sexp.from_array(ast) | |
code = "lambda {|_i,_o,_h|\n#{@processor.process(sexp)}}" | |
handler = @handlers[file] = eval(code) | |
end | |
lambda { |input,output| handler.call(input,output,params) } | |
end | |
end | |
end | |
end | |
run Esoteric::DT::Server.new(::File.expand_path(::File.dirname(__FILE__))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
「○○くんて、もしかして童貞?」 | |
「どどど童貞ちゃうわっ!どど童貞ちゃうわっ!どどど…童貞ちゃうわっ!」 | |
「えー。その慌てっぷりが余計怪しなぁw」 | |
「…どどどどど童貞ちゃうわっ!童貞ちゃうわっ!ど童貞ちゃうわっ!どど童貞ちゃうわっ!…童貞ちゃうわっ!」 | |
「はいはい、わ、わかったってば。そんなにムキになんないでよ。」 | |
「…どどどどど童貞ちゃうわっ!どどどど童貞ちゃうわっ!…童貞ちゃうわっ!」 | |
「だから、わかったってば。もう言わないから。」 | |
「…どどどどど童貞ちゃうわっ!ど童貞ちゃうわっ!ど…童貞ちゃうわっ!」 | |
「いやその、なんか、ほんとごめんね。そんな気にしてると思わなかったから…」 | |
「どど…」 | |
「(ほんとキモいなぁ…)」 | |
「…」 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment