てきとう

てきとう

やたーw

Grassインタプリタできたよーwww
無駄に長いのでソースは最後wwwww
とりあえず出来が酷いwwww動くか怪しいしwwwwwwwww
完成したのに今一つGrassの動作が解ってないwwwwww意味ねえwwwwwwww
しかもwwwwwErlangぽさがwwwwwwほとんどねえwwwwwwww

仕様wWWwwww:

  • 全角のw、WなんてwwwwwwErlangが扱えるわけwwwwwwwねーよwwwwwww
  • まともに動くwwwwwwwわけwwwwwねーよwwwwwwwwwwww


サンプル、というか検証に使ったテストコードはirie @ ウィキ - grass.elから(無断でこっそり)お借りしましたww*1
この場でお礼を申し上げますwwwww本当にありがとうございましたwwwwwwwwwwwww*2

ここのHello, world動かなかったwwwwwwwwエラー表示がwwwwww1000行とかwwwwww
実装失敗wwwwwwwww


今後の予定ww:
もしこれ以上wwww弄るwwwとかwwwww

  • サーバ化するとwwwwwgen_server辺りの練習にwwwwwwならねえwwwwwwwwwww
  • i/1が現状だと残念wwwwwwwすぎるwwwwwwwwwwどうにかしないとwwwwwwwwwww


でwwwwww長すぎるwwwwwwwのでwwwww最後に来たソースwwwwwww

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% @author Zubenalt
%% @copyright 2008 Zubenalt
%% @doc An implementation of Grass, the grass-planting programming language.
%% @reference
%% See <a href="http://www.blue.sky.or.jp/grass/">Grass official home page</a> 
%% for more information about Grass.
%% @version 0
%% @end
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

-module(grass).
%% -compile(export_all).


-export([test/0,
	 eval/1,
	parse/1,scan/1,exec/1]).

%% @spec test()-> [ok]
%% @doc evaluate
test()->
    lists:map(fun(X)->
		      io:format("~s~n",[element(1,X)]),
		      eval(element(2,X)),
		      io:format("~ndone.~n")
	      end, 
	      [{"Calculate 1 + 1 and print the result by the number of 'w'",
	       "wwWWwvwwwwWWWwwWwwWWWWWWwwwwWwwvwWWwwwWwwwwWwwwwwwWwwwwwwwww"},
	      {"Calculate (2^2)^2 and print the result by the number of 'w'",
	      "wwWWwWWWwvwWWwwWwwwWwwwwwWwwwwwwww"},
	      {"Print printable ASCII characters",
	       "wWWwWWWWwvwwWWwWWWwvwwwWWWwwWwwWWWWwvwWWwwwWWWwWWWWWwwWwwwwwWwwwWWWWWWWWwWWWWwwwWwwwWWWWWWWWWWwWWWWwwwwwwwwwwwwwwwWwwwwwwwwwwwwwwwwwWWWwwwwwwwwwwwwwwwWww"},
	      {"Print fib(n) by the number of 'w' from n=1 to n=12",
	      "wwWWwwWwwvwwWWWwWWWwvwWWwWwvwvwwWWWwwvwwvwWWWwwWWwWwwwwwvwwwWWwwwWWwvwwwWWWWwwWWWWWWWWwwWWWWWwwWwwWwwwwwwwwwwwwvwwwWWWwwWwwWWWWwvwwWWwvwWWWwwWwWWWWWwwWwwwwwwWwwwWWWWWwWwwwwwwwwwwwwwwwwwwwwWWWWWwWwwwwwwwwwwwwwwwwwwwwwwwWWWWWWWWWWwwwwwwwwwwwwwwwwwwwwwwWwwwwwwwwwwwwwwwwwwwwwwwwwWWWWWWWWWWWWWWWWWWWWWWWWwwwvwwwwWWWWWwwWWWWwwwwwwwwWwwwwWWWWWWWWWWWwwwwWWWWWWWWWWWWWWwWwWwwwwwwwwwwWwwwwwwwwwWwwwwwwWwwwwwwvwWWWWWwwwwWwWwwwwwwwWwwWWwWWWWWWWWWWWWWWWWWwwwwwwwWwwwwwwwwwwwwwwwWwwwwwwwwwwwWwwww"}]).


%% @spec eval(Src::string())->ok
%% @doc evaluates Grass code.
eval(Src)->
    exec(parse(Src)).

%% @spec parse(Src::string())->code()
%% @doc generates internal expression from Grass code.
parse(Src)->
    parse_prog(scan(Src)).

%% @spec scan(Src::string())->[{char(),int()}]
%% @doc tokenize Grass code.
scan(S)->
    scan(S,[]).

%% @spec exec(code())->{ok, env()}
%% @doc evaluates internal expression.
exec(Code)->
    transform({Code,e_0(),d_0()}).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% private functions (not exported)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% @type val() = {abs, integer(), code()} | {app, integer(), integer()}
%%              |{prim, function()} | {char, char()}
%% @type code()=[val()]
%% @type f()   ={code(), env()}
%% @type env() =[f()]
%% @type dump()=[{code(),env()}]
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

parse_app(Src)->
    parse_app(Src,[]).
parse_app([],Res)->
    lists:reverse(Res);
parse_app([{$W,N1}|
	   [{$w,N2}|T]],Res)->
    parse_app(T,[{app, N1, N2}|Res]);
parse_app(_,_)->
    throw({failed, {sytax_error, unknown_state}}).

parse_abs([{$w,N}|T]) ->
    {abs, N, parse_app(T,[])};
parse_abs(_) ->
    throw({failed, {syntax_error, unknown_state}}).

parse_prog(T)->
    lists:map(fun(L)->
		      case hd(L) of
			  {$w,_} ->
			      parse_abs(L);
			  {$W,_} ->
			      parse_app(L)
		      end
	      end, split(T)).

split(Src)->
    split(Src,[]).
split(T,Res)->
    {L,R}=lists:splitwith(fun(X)-> element(1,X)=/=$v end,T),
    case R of
	[_|[]]->
	    throw({failed, syntax_error});
	[Rh|Rt] ->
	    case Rh of
		{$v,1}->
		    split(Rt,[L|Res]);
		_->
		    throw({failed, {syntax_error, v_duplicated}})
	    end;
	[] ->
	    lists:reverse([L|Res]);
	_ ->
	    throw({failed, sytax_error})
    end.

scan([],Res) ->
    lists:reverse(Res);
scan([$w|T],[]) ->
    scan(T,[{$w,1}]);
scan([_|T],[]) ->
    scan(T,[]);
scan([H|T],Res) when (H=:=$w) or (H=:=$W) or (H=:=$v)->
    case hd(Res) of
	{H,N}->
	    scan(T,[{H,N+1}|tl(Res)]);
	_->
	    scan(T,[{H,1}|Res])
    end;
scan([_|T],Res) ->
    scan(T,Res).

%% @spec transform({C::code(),E::env(),D::dump()})->{ok, env()}
transform({[], [_], []})->
    ok;
transform({[{abs, 1, C_}|C], E, D})->
    transform({C, [{C_, E}|E], D});
transform({ [{abs,N,C_}|C], E, D}) ->
    transform({C, [{[{abs,N-1,C_}], E}|E ], D});
transform({[], [F|E], [{C_,E_}|D]}) ->
    transform({C_, [F|E_],D});
transform({[{app, M, N}|C], E, D}) ->
    F=lists:nth(M,E),
    V=lists:nth(N,E),
    case F of
	{prim, X}->
	    transform({C,[X(V)|E],D});
	{char, _} ->
	    transform({C,[char_eq(F,V)|E],D});
	{C_, E_} ->
	    transform({C_, [V|E_], [{C,E}|D]})
    end.

e_0()->
    [out(),succ(),w(),in()].

d_0()->
    [{[{app,1,1}],[]},{[],[]}].

out()->
    {prim, fun o/1}.
in()->
    {prim, fun i/1}.
succ()->
    {prim, fun succ/1}.
w()->
    {char, $w}.

o({char, C})->
    io:format("~c",[C]),
    {char, C}.

i(X)->
    case io:get_chars('',1) of
	eof-> X;
	[C] ->
	    {char, C}
    end.
succ({char, C})->
    {char, (C+1) rem 256}.

church_true()->
    {[{abs, 1, [{app, 3, 2}]}], [{[],[]}]}.
church_false()->
    {[{abs, 1, []}], []}.

char_eq({char, C1}, {char, C2})->
    case C1 of
	C2 -> church_true();
        _-> church_false()
    end;
char_eq(_,_) ->
    church_false().

草生やしなれていないから疲れる(´・ω・`)

*1:というかtest/0の4つしか試してないwwwwwwwwwwwうぇwwwwwwwwwww

*2:ほぼコードが書けないので非常にありがたかったです。