スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

--.--.-- | スポンサー広告

[Lua] 明示的グローバル変数宣言モジュール

先日のコードを少し修正しました。

とくちょう
- 以下のようにグローバル変数を明示的に宣言できます。

  global "myvar"

 同時に値を入れる機能は削除しました。(空の関数でglobalを代替できなくなるため)
- グローバル変数にnilを代入しても「存在」はそのままです。
(暗黙的に宣言されたグローバル変数は、use_explicit_global()時に自動的に「宣言済み」になります)
- メインチャンク(=関数の外)での暗黙・明示をuse_explicit_global()の引数で選択できます。
(デフォルトは暗黙のほうです)
- use_implicit_globals()でモジュールの機能をOFFにして、通常と同じ動作になります。
- 関数はメインチャンク(=関数の外)以外では明示的宣言が必要です。

- このモジュールを使って組んだコードをこのモジュールを使わないで動かす場合、以下のような宣言をすれば問題なく動きます。

  function global() end
function use_explicit_globals() end
function use_implicit_globals() end


暗黙・明示はソース中の宣言位置によって異なります。


                C | メインチャンク| それ以外(関数内)
-------------------------------------------------------------------------
Luaの通常動作          implicit | implicit | implicit
use_explicit_globals()     implicit | implicit | explicit
use_explicit_globals(true) &
       関数値以外の場合 implicit | explicit | explicit
         関数値の場合 implicit | implicit | explicit

implicit: 暗黙 explicit: 明示 です。

問題点:
- setfenvでグローバル関数全体をあらわすテーブルを変更したら多分妙なことになる。
- use_explicit_globals()が呼ばれたときに既に暗黙的に呼ばれたグローバル変数のうち値がnilのものは「宣言済み」とは解釈されない。(これはLuaのグローバル変数は「値がnilである」のと「存在しない」は同じ扱いだから仕方ないです)

せっかくなのでLuaの本家MLに投げてみましたが、何か返事が来るだろうか、はたまた無視されるやら。

コードは以下に。



----------- example ------------

require "explicit_globals"
use_explicit_globals(true) -- メインチャンクでも明示的な宣言を行う

--- OK case
global "my_global_variable"
my_global_variable = 1
local a = my_global_variable

--- NG case
my_undeclared_variable = 1 -- NG
local a = my_undeclared_variable2 -- NG

--- functions declarations
function undeclared_global_func() end --- ok
undeclared_global_func2 = function() end --- ok

function test()
global "my_global_func"
function my_global_func() end --- ok

function undeclared_global_func3() end --- NG
end
test()



----------- explicit_globals.lua ------------

-- table for checking global var declaration
local gdef = {}
local gdef_enabled = nil

-- the function to define global vars
function global(n)
if not gdef_enabled then
error("calling function global() when explicit-globals not enabled",2)
end
if gdef[n] == true then
error("re-definition of global \"" .. tostring(n) .. "\"",2)
end
gdef[n] = true
return
end

local function registerglobal(t,n,v)
gdef[n] = true
rawset(t,n,v)
end

-- forbid implicit definition of global vars
function use_explicit_globals( is_explicit_in_main_chunk )

-- set metatable for gloval environment
local mt = getmetatable(_G)
if mt == nil then
mt = {}
setmetatable(_G, mt)
end

-- include implicitly-declared globals in gdef table,
-- in case some of it becomes nil and __index,__newindex be called.
-- drawback: if the value is nil now, it will not be included.
for k,v in pairs(_G) do
gdef[k] = true
end

mt.__newindex = function (t,n,v)
if gdef[n] ~= nil then -- declared global
rawset(t,n,v);return
end
if debug.getinfo(2,"S") == nil then
registerglobal(t,n,v);return
end
local w = debug.getinfo(2,"S").what
if w == "C" then -- in C chunk
registerglobal(t,n,v);return
end
if ( not is_explicit_in_main_chunk and w == "main" ) then -- in main chunk
registerglobal(t,n,v);return
end
if type(v) == "function" then
-- funtcion value
if w == "main" then
-- declatration of functions in main chunk is ok.
registerglobal(t,n,v);return
else
error("assignment of undeclared global function \"" .. tostring(n)
.. "\" outside of main chunk. use global(\"var\", val)", 2)
end
else
-- not function value
error("assignment of undeclared global \"" .. tostring(n)
.. "\". use global(\"var\", val)", 2)
end
end
mt.__index = function (t,n)
if gdef[n] == nil and debug.getinfo(2,"S").what ~= "C" then
error("attempt to use undeclared global \"" .. tostring(n)
.. "\". use global(\"var\", val)", 2)
end
return rawget(t, n)
end
gdef_enabled = true
end

-- back to normal, implicit global declaration.
function use_implicit_globals()
local mt = getmetatable(_G)
if mt ~= nil then
mt.__newindex = nil
mt.__index = nil
end
gdef_enabled = nil
end

----------- explicit_globals.lua ------------
スポンサーサイト

2005.08.29 | Comments(2) | Trackback(0) | Lua

コメント

explicit_globalsモジュールについて

はじめまして。izariuo440といいます。

explicit_globalsモジュールを大変ありがたく使わせてもらっています。ただ、ひとつ気になったところがあったのでご報告を。

mt.__index = function (t,n)

if gdef[n] == nil and debug.getinfo(2,"S").what ~= "C" then

という部分でdebug.getinfo(2,"S")がnilを返すとまずいことになるみたいです。
Lua5.1とかのバイナリで試しても問題なかったのですが、自分で作ってるアプリで試したらまずいことになりました。
nilチェックをいれたら問題なく動きました。

以上ご報告でした。

Lua関係の記事はいつも非常に楽しませてもらっています。
これからも期待してますので・・・。

2006-04-24 月 07:43:58 | URL | izariuo440 #VWFaYlLU [ 編集]

izariuo440さんはじめまして。コメントありがとうございます~。

Cからlua_settable()でグローバルを設定する場合にdebug.getinfo(2,"S")がnilになるみたいですね。

対処しておきました。
ご指摘恐れ入りますm(__)m

>Lua関係の記事はいつも非常に楽しませてもらっています。
>これからも期待してますので・・・。

とても嬉しいです。
ちょっとネタ切れぎみですががんばります(^^)

2006-04-27 木 03:46:11 | URL | はむ! #sqCyeZqA [ 編集]

コメントの投稿


秘密にする

新しい記事へ <<  | HOME |  >> 古い記事へ

広告:

カテゴリ展開メニュー

  • 未分類(13)
  • Lua(38)
  • プログラミング(11)
  • 食べ物(3)
  • SPAM(2)
  • ゲーム開発(4)
  • GIS/GPS/GoogleMaps(2)
  • スポーツ(1)
  • Skype API(1)
  • AR(1)

はてブ ランキング

ブログ全体: このWikiのはてなブックマーク数

プロフィール

はむ!

Author:はむ!
よく使う言語・環境:
C++,C,Lua,java,VBA,DB
たまにPHPとかjavascript
血液型:O型

メール: lua%ham.nifty.jp
(%を@に変えてください)
ついったー: @hammmm

Lua関連アンテナ

ブロとも申請フォーム

この人とブロともになる

全記事表示リンク

全ての記事を表示する

ブログ内検索


上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。