Introducing
Your new presentation assistant.
Refine, enhance, and tailor your content, source relevant images, and edit visuals quicker than ever before.
Trending searches
えんいー
未来の部屋
Regexp Assemble for PHP
萌え萌えCSS
sexyhook テスト用の接合部の作成
新潟アクセス修飾子
とある関数の電脳戦(バトルプログラム)
自己紹介
hiphop php でPHPからジェネレートされた
C++コードを読んでみよう
lua構文ハック
perlの魔術的ライブラリ
Regexp AssembleをPHPに移植。
正規表現を機械的に作成する。
テスト用の接合部を
後付で創りだす
必要悪のライブラリ
音声認識を利用して
家電制御を制御する
未来の部屋
自己紹介
こんちにはー
jQueryを
萌え化する
プロセスの乗っ取りを防ぐ
アンチフックの話
そして、攻性防壁の構築。
一部アセンブラ
by rti
public
protected
private
そして niigata
名前: rti
仕事: 起業準備中という名の引きこもり??
肩書き: シーランド公国伯爵
特技: イオナズンが使えます。
最近のトレンド: 音声認識
PHPをC++に変換する
hiphopの変換方式を
めぐる長い旅の話
http://d.hatena.ne.jp/rti7743/
http://rtilabs.net/
https://twitter.com/#!/super_rti
http://d.hatena.ne.jp/rti7743/20100113/1263332839
http://d.hatena.ne.jp/rti7743/20111220/1324389840
http://rtilabs.net/files/2011_11_02/
http://prezi.com/2r6wmrriyeqb/niigata/
http://d.hatena.ne.jp/rti7743/20120104/1325668680
http://rtilabs.net/files/2010_12_24/moemoe_css/
http://d.hatena.ne.jp/rti7743/20111225/1324817155
簡易スクリプトとしての利用
TASでの利用
設定ファイルでの利用
プログラム言語とコメント
答え
luaのコメントは // ではなく -- です。
主に言語の中に組み込む用途に使われることが
多いプログラム言語です。
むかつきますよね。
スクリプト
設定ファイルをプログラム化
//足し算をします
function add(a,b)
return a + b
end
lua構文ハック
村人A.lua
lua
config.lua
lua
欝になりますね。
だけど、
やっぱり、C/C++に組み込む言語だったら、
コメントは // にして統一感を持たせたいです。
今日は夜道に注意しよう・・・
コメントが // で書けない
プログラム言語なんて氏ねば(ry
Luaなんて知ってるよ。
って人に質問です。
ゲーム
本体
C/C++
server_ip = "192.168.10.10"
server_port = 80
user_agent = "Hogehoge/v2"
if user == "rti" then
user_agent = "rti/v3"
endif
エミュレータ
本体
プログラム
本体
Luaって何?
speak("山のむらにようこそ");
wait();
local yorn = yorn("前に来たことありますか?");
if yorn == 1 then
speak("またきてくれてありがとう");
else
speak("はじめまして!!");
endif
lua
-- 足し算をします
function add(a,b)
return a + b
end
C // (正確には /* */)
C++ //
C# //
D //
java //
javascript //
PHP //
ruby #
perl #
python #
sh #
lua --
SQL --
haskell --
basic rem
COBOL *
エミュレータに組み込まれているlua。
キー操作などをプログラム化し、
乱数などの最適解を自動で探索させる。
世界記録がどんどん塗り替えられる。
追記回数が減って、作成が容易になる。
なんて、ことは言ってはいけません。
lua
なんで、
C,C++に組み込む言語なのに
コメントが -- なのか?
(ガチCのコメントは /* */ ですけども)
設定ファイルの構文をluaに丸投げ。
httpd.conf とかみたいに階層構造などを持つものだと効果的かも。
ただし、GUIでの設定画面との共存が難しい。
足し算する Lua のコードは動きません。
なぜでしょうか?
さて、
今日は Lua の話をします。
参考:
氏ねとかいうと、
会場の半分以上を
敵に回すので危険が危ないです。
LL言語と SQLの関係に似てます。
最近は、TASさんの友達らしいです。
http://www6.atpages.jp/appsouko/work/TAS/doc/bot.html
既存のコメント
// をつけてあげればいいじゃない。
無事動くと。簡単でしょ。
ブロックコメントの処理も入ってる
なんで pascal調?
lua構文ハック
C/C++から組み込まれることが
多いのわかってんの?
----llex.c---------
case '/': { /* '//' (comment) */
next(ls);
if (ls->current == '/'){ /* short comment */
while (!currIsNewline(ls) && ls->current != EOZ)
next(ls); /* skip until end of line (or end of file) */
break;
}
else {
return '/';
}
}
-------------------
//足し算をします
function add(a,b)
return a + b
end
//足し算をします
function add(a,b) {
return a + b
}
//足し算をします
function add(a,b)
return a + b
end
次にむかつくところを
見てみましょう。
----llex.c---------
case '-': { /* '-' or '--' (comment) */
next(ls);
if (ls->current != '-') return '-';
/* else is a comment */
next(ls);
if (ls->current == '[') { /* long comment? */
int sep = skip_sep(ls);
luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */
if (sep >= 0) {
read_long_string(ls, NULL, sep); /* skip long comment */
luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */
break;
}
}
/* else short comment */
while (!currIsNewline(ls) && ls->current != EOZ)
next(ls); /* skip until end of line (or end of file) */
break;
}
-------------------
//足し算をします
function add(a,b)
return a + b
end
ムカツキますよね。
オープンソースなんだから、
文句があるなら
自分で直せばいいじゃない。
これで、OK
手が勝手にタイプしてしまう。
{} は、テーブル
----llex.c---------
case '/': { /* '//' (comment) */
next(ls);
if (ls->current == '/'){ /* short comment */
while (!currIsNewline(ls) && ls->current != EOZ)
next(ls); /* skip until end of line (or end of file) */
break;
}
else {
return '/';
}
}
-------------------
字句解析 llex ではなく、
構文解析 lparse.c でやる必要がある。
{}も作ってあげれば・・・
そのまま
llex.c でやると
バディングしてしまう。
さっきと同じように、
llex.c で、
{ } の処理を
書けばいいんじゃね?
a = {}
b = {1, 2, 3 , 4}
と、おもうぢゃん
だけど、これ動きません。
lua で
{} は、テーブル(配列兼MAPみたいなもの) になってます。
if文
なぜ else if ではなく elsif なのか。
luaはよく設計されている言語
lua構文ハック
----lparse.c---------------------------------
static void ifstat (LexState *ls, int line) {
FuncState *fs = ls->fs;
int escapelist = NO_JUMP;
test_then_block(ls, &escapelist);
while (ls->t.token == TK_ELSEIF)
test_then_block(ls, &escapelist);
if (testnext(ls, TK_ELSE))
block(ls);
check_match(ls, TK_END, TK_IF, line);
luaK_patchtohere(fs, escapelist);
}
----------------------------------------------
c-like
if (hogehoge == 1) {
func1()
} else if (hogehoge == 2) {
func2()
} else if (hogehoge == 3) {
func3()
} else {
func4()
}
A
だけど、
そんなの関係ないしww
パースを簡単にして速度を稼ぐ。
実に、構文がよく設計されてますね。
B
if (hogehoge == 1) then
func1()
elsif (hogehoge == 2) then
func2()
elsif (hogehoge == 3) then
func3()
else
func4()
end
B
if (hogehoge == 1) then
func1()
elsif (hogehoge == 2) then
func2()
elsif (hogehoge == 3) then
func3()
else
func4()
end
----lparse.c---------------------------------
static void ifstat (LexState *ls, int line) {
FuncState *fs = ls->fs;
int escapelist = NO_JUMP;
test_then_block(ls, &escapelist);
while (ls->t.token == TK_ELSEIF)
test_then_block(ls, &escapelist);
if (testnext(ls, TK_ELSE))
block(ls);
check_match(ls, TK_END, TK_IF, line);
luaK_patchtohere(fs, escapelist);
}
----------------------------------------------
if (hogehoge == 1) then
func1()
elsif (hogehoge == 2) then
func2()
elsif (hogehoge == 3) then
func3()
else
func4()
end
----lparse.c---------------------------------
static void ifstat (LexState *ls, int line) {
FuncState *fs = ls->fs;
int escapelist = NO_JUMP;
test_then_block(ls, &escapelist);
while (ls->t.token == TK_ELSEIF)
test_then_block(ls, &escapelist);
if (testnext(ls, TK_ELSE))
block(ls);
check_match(ls, TK_END, TK_IF, line);
luaK_patchtohere(fs, escapelist);
}
----------------------------------------------
C
----lparse.c-------------------------------------
static void ifstat (LexState *ls, int line) {
FuncState *fs = ls->fs;
int escapelist = NO_JUMP;
int isbracket = 0;
test_then_block(ls, &escapelist,&isbracket);
if (isbracket) {
while(1) {
check_match(ls, '}', TK_IF, line);
if (!testnext(ls, TK_ELSE)) {
break;
}
if ( ls->t.token == TK_IF ) {
test_then_block(ls, &escapelist,&isbracket);
if (!isbracket) {
error_expected(ls, '{');
}
continue;
}
else {
checknext(ls,'{');
block(ls);
}
}
}
else {
while (ls->t.token == TK_ELSEIF)
test_then_block(ls, &escapelist,&isbraket);
if (testnext(ls, TK_ELSE))
block(ls);
check_match(ls, TK_END, TK_IF, line);
}
luaK_patchtohere(fs, escapelist);
}
--------------------------------------------
D
----lparse.c-------------------------------------
static void ifstat (LexState *ls, int line) {
FuncState *fs = ls->fs;
int escapelist = NO_JUMP;
int isbracket = 0;
test_then_block(ls, &escapelist,&isbracket);
if (isbracket) {
while(1) {
check_match(ls, '}', TK_IF, line);
if (!testnext(ls, TK_ELSE)) {
break;
}
if ( ls->t.token == TK_IF ) {
test_then_block(ls, &escapelist,&isbracket);
if (!isbracket) {
error_expected(ls, '{');
}
continue;
}
else {
checknext(ls,'{');
block(ls);
}
}
}
else {
while (ls->t.token == TK_ELSEIF)
test_then_block(ls, &escapelist,&isbraket);
if (testnext(ls, TK_ELSE))
block(ls);
check_match(ls, TK_END, TK_IF, line);
}
luaK_patchtohere(fs, escapelist);
}
--------------------------------------------
----lparse.c---------------------------------
static void ifstat (LexState *ls, int line) {
FuncState *fs = ls->fs;
int escapelist = NO_JUMP;
test_then_block(ls, &escapelist);
while (ls->t.token == TK_ELSEIF)
test_then_block(ls, &escapelist);
if (testnext(ls, TK_ELSE))
block(ls);
check_match(ls, TK_END, TK_IF, line);
luaK_patchtohere(fs, escapelist);
}
----------------------------------------------
then の代わりに
{ を検出したら分岐
c-like な構文と LUAの秘密。
他のロジックもこんな感じで、
よく設計されています。
c-like
既存のluaコードのために
両対応しているので
余計にコードが増えてます。
lua
もし、 else if だったら while(elsif) で
待てないので、字句解析か構文解析に負担。
テストコード
俺は、 elsif ではなく、
else ifと書きたい。
しかも、C言語風に { } で。
lua
だけど・・・
パースを簡単にして速度を稼ぐ。実に、構文がよく設計されてますね。
なんでモードを切り替えないといけないの?
SJISを通すモードを作りました。
Windows/Linuxクロスプラットフォーム
C/C++の憂鬱
日本語windowsの文字コード
luaを
もっとハックしよう
//SJISを有効にするモードへ
lua_setmultibyte(L,1);
UTF-8 BOMあり
UTF-8 BOMなし
SJIS
MS-DOSからの歴史的経緯。
ASCIIと2バイト目が文字がある被る悲しい子。
→ダメ文字 表\ etc..
OK
gcc
NG
OK
LuaをSJISで書くと
ダメ文字問題がある。
オプションが必要
理由
// Luaを開く
lua_State* L = luaL_newstate();
//SJISを有効にするモードへ
lua_setmultibyte(L,1);
UTF16
g++
OK
C#や一部環境はこちら。
昔からプッシュされているけど流行らない不憫な子。
2バイト目に0x00が入るという、
C言語との相性の悪さが光る
オプションが必要
SJISを通そう。
OK
NG
何がダメ文字かどうかは、
文字コードによって変わる。
UTF-8のようにASCIIとの
競合がない文字コードもある。
世の中の人が全員SJISを
使っているわけではない。
visual stuido
(cl.exe)
挙動不審になることがある
UTF8
Web系とかを中心にしたトレンド。
Windowsで一部のソフトが微妙な具合でサポートしてる。
ってゆーか、WindowsのUTF16対応は早すぎたんだよ。
utf16と共にBOMというトリックスターがいるw
唯一、クロスプラットフォームにできそうな
文字コードがSJISぐらいしかない・・・
SJISを通すパッチの先駆者たちに感謝
luaでの this 引き回し
thisを引き回すことを前提にした tag の導入
比較してみよう。ちょっと楽になった?かんじかなぁ
luaからのコールバックには this はない。
初期化部
tag
lightuserdataという
特殊なテーブルに入れる。
名前のラベルは "_this"など
適当に決めるらしい。
luaオリジナル
初期化部
luaを
もっとハックしよう
初期化部
// Luaを開く
lua_State* L = luaL_newstate();
//thisのセット
lua_pushlightuserdata(L ,(void*) this);
lua_setfield(L,"_this");
// Luaを開く
lua_State* L = luaL_newstate();
//this保存
lua_setusertag(L,(void*)this);
C# / Builderの tag のようなものが
あってもいいじゃない
// Luaを開く
lua_State* L = luaL_newstate();
//this保存
lua_setusertag(L,(void*)this);
A
// Luaを開く
lua_State* L = luaL_newstate();
//thisのセット
lua_pushlightuserdata(L ,(void*) this);
lua_setfield(L,"_this");
C++に導入するときに
thisポインタを
引き回したい時が
あります。
class myscript {
//luaに登録する関数 コールバックされる。
static int l_func_callback(lua_State* L)
{
//thisが使いたい
this->method() ....
}
myscript()
{
}
}
A
利用
this引き回しの簡易化
利用
B
//thisを使いたいシーンが来たら、
lua_getfield(L,LUA_REGISTRYINDEX,"_this");
myclass* p = (myclass*)lua_touserdata(L,-1);
lua_pop(L,1);
//p に this が入っているよ!!
p->myFunc();
//thisを追加したシーンが来たら
myclass* p = (myclass*)lua_getusertag(L);
//p に this が入っているよ!!
p->myFunc();
B
//thisを追加したシーンが来たら
myclass* p = (myclass*)lua_getusertag(L);
//p に this が入っているよ!!
p->myFunc();
//thisを使いたいシーンが来たら、
lua_getfield(L,LUA_REGISTRYINDEX,"_this");
myclass* p = (myclass*)lua_touserdata(L,-1);
lua_pop(L,1);
//p に this が入っているよ!!
p->myFunc();
せっかくだから、XSS対策も。
Web制作言語といえばPHP
プログラムとHTMLの反転
余談
HTMLテンプレートエンジン
<b><?lua print func(123) ?></b>
<?php echo "hello world!" ?>
luaを
もっとハックしよう
基本的に、outテーブルのものしか出力させない。
out に突っ込んだものは、
ディフォルトでタグエスケープされる。
アプリの設定画面とか
デザインが作りやすい
webにしたいときあるじゃん
<BR><!--?LE:YThreads--><BR><BR>
<DIV ALIGN="CENTER">
<TD>
<FORM action="../test/bbs.cgi" method=post><BR>
<INPUT type=hidden value="<!--?V:YItaName-->" name=bbs>
</form>
</TD>
</TR>
</TBODY>
PHPの Zend Engineは、
当初は PHP本体から切り離せるよーな
設計思想だったそーですが、
いつの間にかその思想は忘れ去らてしまいました。(と、いう話を聞いた)
仮に切り離せたとしても、
ランタイムが巨大になるとおもいますけども。
print "<b>";print func(123);print "</b>"
PHPなどのように、
luaを使うことはできないか?
luaでweb開発
//計算
out = {"value" = 123}
//HTML表示
webload("index.tpl",out);
<?lua print "hello world!" ?>
HTMLの部分を print に置き換える。
<?lua ?> の中身はそのまま記述。
JSPとかと発想は同じw
windowsSDKで作るより
htmlで作れるとデザインの自由度が上がるし。
文字列リプレースとか、
for とか ifとか自分で作るのはめんどいし。
その他のハックまとめ
静的言語でのeval
CM
C++での言語内言語
http://d.hatena.ne.jp/rti7743/20120312
これらを組み込んだ、
lua
lua構文ハック
C++ libdcompile
サイズが小さい。(300kb程度)
おまけ
音声認識
ホームコントロール
LLVMを利用したソリューション
libやincludeファイルが必要
V8(javascript)
SJIS対応にする拡張
lua_setmultibyte(L,1); //これでSJIS対応
this引き回し簡略化
lua_setusertag(L,(void*)this);
PHPみたいに webに luaを
hello <?= "word" ?><?lua hoge() ?>
chromeのjavascriptエンジン。
動作が超早い。
C# CSharpCodeProvider
naichichi2 作ってます。
オープンソースなんだから、
いろいろ改造して遊びましょう。
boost.python
C#ランタイムに含まれる。
ただ、クロスプラットフォームを考えると・・・
monoだと別のソリューション?
https://github.com/rti7743/kaden_voice/tree/master/naichichi2
使ったことない・・・w