Commit 079b7966 authored by Vinicius Jarina's avatar Vinicius Jarina
Browse files

Fixed #44 Getting .NET type after using luanet.import_type

Added MonoLuaInterface samples.
parent e6a35f4c
...@@ -103,45 +103,46 @@ namespace NLua ...@@ -103,45 +103,46 @@ namespace NLua
//private object luaLock = new object(); //private object luaLock = new object();
private bool _StatePassed; private bool _StatePassed;
private bool executing; private bool executing;
static string initLuanet = static string initLuanet =
"local metatable = {} \n" + @"local metatable = {}
"local import_type = luanet.import_type \n" + local rawget = rawget
"local load_assembly = luanet.load_assembly \n" + local import_type = luanet.import_type
" \n" + local load_assembly = luanet.load_assembly
"-- Lookup a .NET identifier component. \n" + luanet.error, luanet.type = error, type
"function metatable:__index(key) -- key is e.g. \"Form\" \n" + -- Lookup a .NET identifier component.
" -- Get the fully-qualified name, e.g. \"System.Windows.Forms.Form\" \n" + function metatable:__index(key) -- key is e.g. 'Form'
" local fqn = ((rawget(self, \".fqn\") and rawget(self, \".fqn\") .. \n" + -- Get the fully-qualified name, e.g. 'System.Windows.Forms.Form'
" \".\") or \"\") .. key \n" + local fqn = rawget(self,'.fqn')
" \n" + fqn = ((fqn and fqn .. '.') or '') .. key
" -- Try to find either a luanet function or a CLR type \n" +
" local obj = rawget(luanet, key) or import_type(fqn) \n" + -- Try to find either a luanet function or a CLR type
" \n" + local obj = rawget(luanet,key) or import_type(fqn)
" -- If key is neither a luanet function or a CLR type, then it is simply \n" +
" -- an identifier component. \n" + -- If key is neither a luanet function or a CLR type, then it is simply
" if obj == nil then \n" + -- an identifier component.
" -- It might be an assembly, so we load it too. \n" + if obj == nil then
" load_assembly(fqn) \n" + -- It might be an assembly, so we load it too.
" obj = { [\".fqn\"] = fqn } \n" + pcall(load_assembly,fqn)
" setmetatable(obj, metatable) \n" + obj = { ['.fqn'] = fqn }
" end \n" + setmetatable(obj, metatable)
" \n" + end
" -- Cache this lookup \n" +
" rawset(self, key, obj) \n" + -- Cache this lookup
" return obj \n" + rawset(self, key, obj)
"end \n" + return obj
" \n" + end
"-- A non-type has been called; e.g. foo = System.Foo() \n" +
"function metatable:__call(...) \n" + -- A non-type has been called; e.g. foo = System.Foo()
" error(\"No such type: \" .. rawget(self, \".fqn\"), 2) \n" + function metatable:__call(...)
"end \n" + error('No such type: ' .. rawget(self,'.fqn'), 2)
" \n" + end
"-- This is the root of the .NET namespace \n" +
"luanet[\".fqn\"] = false \n" + -- This is the root of the .NET namespace
"setmetatable(luanet, metatable) \n" + luanet['.fqn'] = false
" \n" + setmetatable(luanet, metatable)
"-- Preload the mscorlib assembly \n" +
"luanet.load_assembly(\"mscorlib\") \n"; -- Preload the mscorlib assembly
luanet.load_assembly('mscorlib')";
static string clr_package = @"--- static string clr_package = @"---
--- This lua module provides auto importing of .net classes into a named package. --- This lua module provides auto importing of .net classes into a named package.
......
...@@ -32,6 +32,7 @@ using System.Collections.Generic; ...@@ -32,6 +32,7 @@ using System.Collections.Generic;
using NLua.Method; using NLua.Method;
using NLua.Exceptions; using NLua.Exceptions;
using NLua.Extensions; using NLua.Extensions;
using KopiLua;
namespace NLua namespace NLua
{ {
...@@ -54,7 +55,7 @@ namespace NLua ...@@ -54,7 +55,7 @@ namespace NLua
public class ObjectTranslator public class ObjectTranslator
{ {
private LuaNativeFunction registerTableFunction, unregisterTableFunction, getMethodSigFunction, private LuaNativeFunction registerTableFunction, unregisterTableFunction, getMethodSigFunction,
getConstructorSigFunction, importTypeFunction, loadAssemblyFunction; getConstructorSigFunction, importTypeFunction, loadAssemblyFunction, ctypeFunction, enumFromIntFunction;
// object to object # // object to object #
public readonly Dictionary<object, int> objectsBackMap = new Dictionary<object, int> (); public readonly Dictionary<object, int> objectsBackMap = new Dictionary<object, int> ();
// object # to object (FIXME - it should be possible to get object address as an object #) // object # to object (FIXME - it should be possible to get object address as an object #)
...@@ -93,7 +94,9 @@ namespace NLua ...@@ -93,7 +94,9 @@ namespace NLua
registerTableFunction = new LuaNativeFunction (ObjectTranslator.RegisterTable); registerTableFunction = new LuaNativeFunction (ObjectTranslator.RegisterTable);
unregisterTableFunction = new LuaNativeFunction (ObjectTranslator.UnregisterTable); unregisterTableFunction = new LuaNativeFunction (ObjectTranslator.UnregisterTable);
getMethodSigFunction = new LuaNativeFunction (ObjectTranslator.GetMethodSignature); getMethodSigFunction = new LuaNativeFunction (ObjectTranslator.GetMethodSignature);
getConstructorSigFunction = new LuaNativeFunction (ObjectTranslator.GetConstructorSignature); getConstructorSigFunction = new LuaNativeFunction (ObjectTranslator.GetConstructorSignature);
ctypeFunction = new LuaNativeFunction (ObjectTranslator.CType);
enumFromIntFunction = new LuaNativeFunction (ObjectTranslator.EnumFromInt);
CreateLuaObjectList (luaState); CreateLuaObjectList (luaState);
CreateIndexingMetaFunction (luaState); CreateIndexingMetaFunction (luaState);
...@@ -194,6 +197,10 @@ namespace NLua ...@@ -194,6 +197,10 @@ namespace NLua
LuaLib.LuaSetGlobal (luaState, "get_method_bysig"); LuaLib.LuaSetGlobal (luaState, "get_method_bysig");
LuaLib.LuaPushStdCallCFunction (luaState, getConstructorSigFunction); LuaLib.LuaPushStdCallCFunction (luaState, getConstructorSigFunction);
LuaLib.LuaSetGlobal (luaState, "get_constructor_bysig"); LuaLib.LuaSetGlobal (luaState, "get_constructor_bysig");
LuaLib.LuaPushStdCallCFunction (luaState,ctypeFunction);
LuaLib.LuaSetGlobal (luaState,"ctype");
LuaLib.LuaPushStdCallCFunction (luaState,enumFromIntFunction);
LuaLib.LuaSetGlobal(luaState,"enum");
} }
/* /*
...@@ -883,10 +890,86 @@ namespace NLua ...@@ -883,10 +890,86 @@ namespace NLua
internal bool MatchParameters (LuaState luaState, MethodBase method, ref MethodCache methodCache) internal bool MatchParameters (LuaState luaState, MethodBase method, ref MethodCache methodCache)
{ {
return metaFunctions.MatchParameters (luaState, method, ref methodCache); return metaFunctions.MatchParameters (luaState, method, ref methodCache);
} }
internal Array TableToArray(Func<int, object> luaParamValue, Type paramArrayType, int startIndex, int count) { internal Array TableToArray(Func<int, object> luaParamValue, Type paramArrayType, int startIndex, int count) {
return metaFunctions.TableToArray(luaParamValue,paramArrayType, startIndex, count); return metaFunctions.TableToArray(luaParamValue,paramArrayType, startIndex, count);
} }
private Type TypeOf (LuaState luaState, int idx)
{
int udata = LuaLib.LuaNetCheckUData (luaState, 1, "luaNet_class");
if (udata == -1)
return null;
ProxyType pt = (ProxyType)objects [udata];
return pt.UnderlyingSystemType;
}
static int PushError (LuaState luaState, string msg)
{
LuaLib.LuaPushNil (luaState);
LuaLib.LuaPushString (luaState, msg);
return 2;
}
#if MONOTOUCH
[MonoTouch.MonoPInvokeCallback (typeof (LuaNativeFunction))]
#endif
[System.Runtime.InteropServices.AllowReversePInvokeCalls]
private static int CType (LuaState luaState)
{
var translator = ObjectTranslatorPool.Instance.Find (luaState);
return translator.CTypeInternal (luaState);
}
int CTypeInternal (LuaState luaState)
{
Type t = TypeOf (luaState, 1);
if (t == null)
return PushError (luaState, "Not a CLR Class");
PushObject (luaState, t, "luaNet_metatable");
return 1;
}
#if MONOTOUCH
[MonoTouch.MonoPInvokeCallback (typeof (LuaNativeFunction))]
#endif
[System.Runtime.InteropServices.AllowReversePInvokeCalls]
private static int EnumFromInt (LuaState luaState)
{
var translator = ObjectTranslatorPool.Instance.Find (luaState);
return translator.EnumFromIntInternal (luaState);
}
int EnumFromIntInternal (LuaState luaState)
{
Type t = TypeOf (luaState, 1);
if (t == null || !t.IsEnum)
return PushError (luaState, "Not an Enum.");
object res = null;
LuaTypes lt = LuaLib.LuaType (luaState, 2);
if (lt == LuaTypes.Number) {
int ival = (int)LuaLib.LuaToNumber (luaState, 2);
res = Enum.ToObject (t, ival);
} else
if (lt == LuaTypes.String) {
string sflags = LuaLib.LuaToString (luaState, 2);
string err = null;
try {
res = Enum.Parse (t, sflags);
} catch (ArgumentException e) {
err = e.Message;
}
if (err != null)
return PushError (luaState, err);
} else {
return PushError (luaState, "Second argument must be a integer or a string.");
}
PushObject (luaState, res, "luaNet_metatable");
return 1;
}
} }
} }
\ No newline at end of file
--require 'luanet'
require 'CLRPackage'
import 'System'
import 'System.Reflection'
local get_flags = luanet.enum(BindingFlags,'GetProperty,IgnoreCase,Public')
local put_flags = luanet.enum(BindingFlags,'SetProperty,IgnoreCase,Public')
local call_flags = luanet.enum(BindingFlags,'InvokeMethod,IgnoreCase,Public')
local function A(a)
return luanet.make_array(Object,a)
end
local empty = A{}
local com_wrapper
local T = luanet.ctype(__ComObject)
local function maybe_wrap(res)
if type(res) == 'userdata' then
if res:GetType() == T then return com_wrapper(res) end
end
return res
end
local function caller(obj,key)
local T = obj:GetType()
return setmetatable({},{
__call = function(t,o,...)
return maybe_wrap(T:InvokeMember(key,call_flags,nil,obj,A{...}))
end
})
end
function com_wrapper(obj)
local T = obj:GetType()
return setmetatable({},{
__index = function(self,key)
local ok,res = pcall(T.InvokeMember,T,key,get_flags,nil,obj,empty)
if not ok then
res = tostring(res)
if res:match 'Member not found' then
return caller(obj,key) --local c =
--~ rawset(self,key,c)
--~ return c
else
error("cannot find "..key,2)
end
else
return maybe_wrap(res)
end
end;
__newindex = function(self,key,value)
T:InvokeMember(key,put_flags,nil,A{value})
end
})
end
com = {}
function com.CreateObject(progid)
local ft = Type.GetTypeFromProgID(progid)
local f = Activator.CreateInstance(ft)
return com_wrapper(f)
end
com.wrap = maybe_wrap
return com
require 'CLRPackage'
import 'System.Reflection'
import 'LuaInterface'
local ctype, enum = luanet.ctype, luanet.enum
-- get all the static methods of LuaDLL and import them into global
local mm = ctype(LuaDLL):GetMethods(enum(BindingFlags,'Static,Public'))
for i = 0, mm.Length-1 do
local name = mm[i].Name
_G[name] = LuaDLL[name]
end
-- we can now do standard Lua API things in Lua...
local L = luaL_newstate()
luaL_openlibs(L)
lua_pushstring(L,"hello dolly")
print(lua_gettop(L))
print(lua_tostring(L,-1))
require 'CLRPackage'
import 'System'
local arr = luanet.make_array(Double,{1,2})
print(arr.Length)
print(arr.Foo)
require 'CLRPackage'
import 'System'
import ('gtk-sharp','Gtk')
import('glib-sharp','GLib')
local ctype = luanet.ctype
Application.Init()
local win = Window("Hello from GTK#")
win.DeleteEvent:Add(function()
Application.Quit()
end)
win:Resize(300,300)
local store = ListStore({GType.String,GType.String})
--local store = ListStore({ctype(String),ctype(String)})
store:AppendValues {"Dachsie","Fritz"}
store:AppendValues {"Collie","Butch"}
local view = TreeView()
view.Model = store
view.HeadersVisible = true
-- the long way to make a column
function new_col(title,kind,idx)
local col = TreeViewColumn()
col.Title = title
local r = CellRendererText()
col:PackStart(r,true)
col:AddAttribute(r,kind,idx)
view:AppendColumn(col)
end
new_col("Dogs","text",0)
--new_col("Name","text",1)
-- and the short way
local col = TreeViewColumn("Name",CellRendererText(),{"text",1})
view:AppendColumn(col)
view.Selection.Changed:Add(function(o,args)
local selected, model, iter = o:GetSelected();
if selected then
local val = model:GetValue(iter,0)
print("selected",val)
end
end)
win:Add(view)
win:ShowAll()
Application.Run()
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
<glade-interface>
<widget class="GtkWindow" id="window1">
<property name="visible">True</property>
<property name="title" translatable="yes">Glade Window</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_CENTER</property>
<property name="modal">False</property>
<property name="default_width">256</property>
<property name="default_height">256</property>
<property name="resizable">True</property>
<property name="destroy_with_parent">False</property>
<property name="decorated">True</property>
<property name="skip_taskbar_hint">False</property>
<property name="skip_pager_hint">False</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
<property name="focus_on_map">True</property>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
<property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
<widget class="GtkLayout" id="layout1">
<property name="visible">True</property>
<property name="width">400</property>
<property name="height">400</property>
<property name="hadjustment">0 0 400 10 212.4 236</property>
<property name="vadjustment">0 0 400 10 212.4 236</property>
<child>
<widget class="GtkLabel" id="label1">
<property name="width_request">38</property>
<property name="height_request">17</property>
<property name="visible">True</property>
<property name="label" translatable="yes">label1</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="x">96</property>
<property name="y">88</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button1">
<property name="width_request">60</property>
<property name="height_request">27</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">button1</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
</widget>
<packing>
<property name="x">88</property>
<property name="y">168</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
</widget>
</glade-interface>
require 'CLRPackage'
import ('System')
import ('gtk-sharp','Gtk')
import ('glade-sharp','Glade')
Application.Init()
local gxml = XML("gui.glade","window1",nil) --(nil,"gui.glade","window1",nil)
--gxml:AutoConnect (nil)
local win = gxml:GetWidget "window1"
win.DeleteEvent:Add(function()
Application.Quit()
end)
local btn = gxml:GetWidget "button1"
btn.Clicked:Add(function(e,a)
-- Console.WriteLine("I was clicked")
-- note how we have to pass an empty Object[] as the last argument!
local args = luanet.make_array(Object,{})
local md = MessageDialog(win,
DialogFlags.DestroyWithParent,
MessageType.Question,
ButtonsType.YesNo, "Are you sure you wanted to click that button?",
args
)
local res = md:Run()
res = luanet.enum(ResponseType,res)
if res == ResponseType.Yes then
Console.WriteLine("ok!")
end
md:Destroy()
end)
Application.Run()
require 'CLRPackage'
import ('gtk-sharp','Gtk')
Application.Init()
local win = Window("Hello from GTK#")
win.DeleteEvent:Add(function()
Application.Quit()
end)
win:Resize(300,300)
local label = Label()
label.Text = "Hello World!"
win:Add(label)
win:ShowAll()
Application.Run()
luanet.load_assembly "System"
Console = luanet.import_type "System.Console"
Math = luanet.import_type "System.Math"
Directory = luanet.import_type "System.IO.Directory"
Console.WriteLine("we are at {0}",Directory.GetCurrentDirectory())
Console.WriteLine("sqrt(2) is {0}",Math.Sqrt(2))
require 'CLRPackage'
import "System"
Console.WriteLine("sqrt(2) is {0}",Math.Sqrt(2))
#!/home/azisa/bin/luai
require 'CLRPackage'
import "System"
import "System.IO"
Console.WriteLine("we are at {0}",Directory.GetCurrentDirectory())
#!/home/azisa/bin/luai
--- another variant of hello3: look, Ma, no globals!
require 'CLRPackage'
local sys,sysi = luanet.namespace {'System','System.IO'}
sys.Console.WriteLine("we are at {0}",sysi.Directory.GetCurrentDirectory())
-- ilua.lua
-- A more friendly Lua interactive prompt
-- doesn't need '=', and will try to print out tables recursively.
-- On Unix, will use readline.so if available.
-- Steve Donovan, 2007
--
local usage = [[ilua -lLtTvsq (lua files)
-l load a library
-L load a library and bring into global namespace
-t <file> write transcript to file; ilua.log if not specified
-T write transcript to file of format ilua_yyyy_mm_dd_HH_MM.log
-s switch off strict mode (don't report undeclared globals)
-v be verbose
-q require standalone expressions to end with '?' (e.g, 23*1.5?)
If a file called ilua-defs is on your library path, it will be loaded first.
]]
local pretty_print_limit = 20
local max_depth = 7
local table_clever = true
local prompt = '> '
local verbose = false
local strict = false
local que = false
-- suppress strict warnings
_ = true
-- imported global functions
local sub = string.sub
local match = string.match
local find = string.find
local push = table.insert
local pop = table.remove
local append = table.insert
local concat = table.concat
local floor = math.floor
local write = io.write
local read = io.read
local savef
local collisions = {}
local G_LIB = {}
local declared = {}
local line_handler_fn, global_handler_fn
local print_handlers = {}
ilua = {}
function ilua.set_writer (writer)
write = writer
end
local num_prec
local num_all
local jstack = {}
local function oprint(...)
if savef then
savef:write(concat({...},' '),'\n')
end
write(...)
--write '\r\n'
write '\n'
end
local function is_map_like(tbl)
for k,v in pairs(tbl) do
if type(k) ~= 'number' then
return true
end
end
return false
end
local function join(tbl,delim,limit,depth)
if not limit then limit = pretty_print_limit end
if not depth then depth = max_depth end
local n = #tbl
local res = ''
local k = 0
-- very important to avoid disgracing ourselves with circular references or
-- excessively nested tables...
if #jstack > depth then
return "..."
end
for i,t in ipairs(jstack) do
if tbl == t then
return "<self>"
end
end
push(jstack,tbl)
-- a table may have a 'list-like' part if it has a non-zero size
-- and may have have a 'map-like' part if it has non-numerical keys
-- you can switch off this cleverness with ilua.table_options {clever = false}
local is_list,is_map
if table_clever then
is_list = #tbl > 0
is_map = is_map_like(tbl)
else
is_map = true -- that is, treat all keys equally
end
if is_list then
for i,v in ipairs(tbl) do
res = res..delim..val2str(v)
k = k + 1
if k > limit then
res = res.." ... "
break
end
end
end
if is_map then
for key,v in pairs(tbl) do
local num = type(key) == 'number'
key = tostring(key)
if not num or (num and not is_list) then
if num then
key = '['..key..']'
end
res = res..delim..key..'='..val2str(v)
k = k + 1
if k > limit then
res = res.." ... "
break
end
end
end
end
pop(jstack)
return sub(res,2)
end
function val2str(val)
local tp = type(val)
if print_handlers[tp] then
local s = print_handlers[tp](val)
return s or '?'
end
if tp == 'function' then
return tostring(val)
elseif tp == 'table' then
if val.__tostring then
return tostring(val)
else
return '{'..join(val,',')..'}'
end
elseif tp == 'string' then
return "'"..val.."'"
elseif tp == 'number' then
-- we try only to apply floating-point precision for numbers deemed to be floating-point,
-- unless the 3rd arg to precision() is true.
if num_prec and (num_all or floor(val) ~= val) then
return num_prec:format(val)
else
return tostring(val)
end
else
return tostring(val)
end
end
function _pretty_print(...)
local args = {n=select('#',...),...}
for i = 1,args.n do
oprint(val2str(args[i]))
end
_G['_'] = args[1]
end
local function compile(line)
if verbose then oprint(line) end
local f,err = loadstring(line,'local')
return err,f
end
local function evaluate(chunk)
local ok,res = pcall(chunk)
if not ok then
return res
end
return nil -- meaning, fine!
end
function eval_lua(line)
-- write to transcript, if open
if savef then savef:write(prompt,line,'\n') end
-- is the line handler interested?
if line_handler_fn then
-- returning nil here means that the handler doesn't want Lua to see the string
line = line_handler_fn(line)
if not line then return end
end
local err,chunk
--~ if not que then -- try compiling first as expression, then as statement
--~ -- is it an expression?
--~ err,chunk = compile('_pretty_print('..line..')')
--~ if err then -- otherwise, a statement?
--~ err,chunk = compile(line)
--~ end
--~ else -- expressions must be explicitly terminated with ?
if line:match '^%s*=' then --or line:match '%?$' then
line = line:gsub ('^%s*=','')
err,chunk = compile('_pretty_print('..line..')')
else
err,chunk = compile(line)
end
--~ end
if not err then
-- we can now execute the chunk
err = evaluate(chunk)
end
if err then -- if there was any compile or runtime error, print it out
oprint(err)
end
end
local function quit(code,msg)
io.stderr:write(msg,'\n')
os.exit(code)
end
-- functions available in scripts
function ilua.precision(len,prec,all)
if not len then num_prec = nil
else
num_prec = '%'..len..'.'..prec..'f'
end
num_all = all
end
function ilua.table_options(t)
if t.limit then pretty_print_limit = t.limit end
if t.depth then max_depth = t.depth end
if t.clever ~= nil then table_clever = t.clever end
end
-- inject @tbl into the global namespace
function ilua.import(tbl,dont_complain,lib)
lib = lib or '<unknown>'
if type(tbl) == 'table' then
for k,v in pairs(tbl) do
local key = rawget(_G,k)
-- NB to keep track of collisions!
if key and k ~= '_M' and k ~= '_NAME' and k ~= '_PACKAGE' and k ~= '_VERSION' then
append(collisions,{k,lib,G_LIB[k]})
end
_G[k] = v
G_LIB[k] = lib
end
end
if not dont_complain and #collisions > 0 then
for i, coll in ipairs(collisions) do
local name,lib,oldlib = coll[1],coll[2],coll[3]
write('warning: ',lib,'.',name,' overwrites ')
if oldlib then
write(oldlib,'.',name,'\n')
else
write('global ',name,'\n')
end
end
end
end
function ilua.print_handler(name,handler)
print_handlers[name] = handler
end
function ilua.line_handler(handler)
line_handler_fn = handler
end
function ilua.global_handler(handler)
global_handler_fn = handler
end
function ilua.print_variables()
for name,v in pairs(declared) do
print(name,type(_G[name]))
end
end
--
-- strict.lua
-- checks uses of undeclared global variables
-- All global variables must be 'declared' through a regular assignment
-- (even assigning nil will do) in a main chunk before being used
-- anywhere.
--
local function set_strict()
local mt = getmetatable(_G)
if mt == nil then
mt = {}
setmetatable(_G, mt)
end
local function what ()
local d = debug.getinfo(3, "S")
return d and d.what or "C"
end
declared.__tostring = true
mt.__newindex = function (t, n, v)
declared[n] = true
rawset(t, n, v)
end
mt.__index = function (t, n)
if not declared[n] and what() ~= "C" then
local lookup = global_handler_fn and global_handler_fn(n)
if not lookup then
error("variable '"..n.."' is not declared", 2)
else
return lookup
end
end
return rawget(t, n)
end
end
--- Initial operations which may not succeed!
-- try to bring in any ilua configuration file; don't complain if this is unsuccessful
pcall(function()
require 'ilua-defs'
end)
-- Unix readline support, if readline.so is available...
local rl,readline,saveline
err = pcall(function()
rl = require 'readline'
readline = rl.readline
saveline = rl.add_history
end)
if not rl then
readline = function(prompt)
write(prompt)
return read()
end
saveline = function(s) end
end
-- process command-line parameters
if arg then
local i = 1
local function parm_value(opt,parm,def)
local val = parm:sub(3)
if #val == 0 then
i = i + 1
if i > #arg then
if not def then
quit(-1,"expecting parameter for option '-"..opt.."'")
else
return def
end
end
val = arg[i]
end
return val
end
while i <= #arg do
local v = arg[i]
local opt = v:sub(1,1)
if opt == '-' then
opt = v:sub(2,2)
if opt == 'h' then
quit(0,usage)
elseif opt == 'l' then
require (parm_value(opt,v))
elseif opt == 'L' then
local lib = parm_value(opt,v)
local tbl = require (lib)
-- we cannot always trust require to return the table!
if type(tbl) ~= 'table' then
tbl = _G[lib]
end
ilua.import(tbl,true,lib)
elseif opt == 't' or opt == 'T' then
local file
if opt == 'T' then
file = 'ilua_'..os.date ('%y_%m_%d_%H_%M')..'.log'
else
file = parm_value(opt,v,"ilua.log")
end
print('saving transcript "'..file..'"')
savef = io.open(file,'w')
savef:write('! ilua ',concat(arg,' '),'\n')
elseif opt == 's' then
strict = true
elseif opt == 'v' then
verbose = true
elseif opt == 'q' then
que = true
end
else -- a plain file to be executed immediately
dofile(v)
end
i = i + 1
end
end
if not arg or arg[0]:match('\\ilua%.lua$') then
print 'ILUA: Lua 5.1.2 Copyright (C) 1994-2007 Lua.org, PUC-Rio\n"quit" to end'
-- any import complaints?
ilua.import()
-- enable 'not declared' error
if strict then
set_strict()
end
local line = readline(prompt)
while line do
if line == 'quit' then break end
eval_lua(line)
saveline(line)
line = readline(prompt)
end
if savef then
savef:close()
end
end
require "CLRPackage"
require "ilua"
require "CLRForm"
import "System.Windows.Forms"
import "System.Drawing"
import "System.IO"
import "TextBox.dll"
local ferr = io.stderr --debug
local append = table.insert
-- it appears necessary to force a delayed evaluation, for which we use a timer....
local timer = Timer()
timer.Interval = 10
local callback
timer.Tick:Add(function()
timer:Stop()
if not pcall(callback) then
ferr:write 'callback hosed\n'
end
end)
local function call_later (fun)
callback = fun
timer:Start()
end
local function readfile (file)
local f = io.open(file,'r')
if not f then return end
local res = f:read("*a")
f:close()
return res
end
local function writefile (file,s)
local f = io.open(file,'w')
if not f then return end
f:write(s)
f:close()
return true
end
function current_line (pane)
return pane:GetLineFromCharIndex(pane.SelectionStart)
end
-- a useful function for selecting lines in Rich text boxes; if lno is not specified,
-- then use the current line
function select_line (pane,lno)
if not lno then -- current line
lno = current_line(pane)
end
local pos = pane.SelectionStart
local start = pane:GetFirstCharIndexFromLine(lno)
pane:Select(start,pos - start + 1)
end
local lines = {}
local list = ListBox()
local no_name = true
local this_dir = Environment.CurrentDirectory
local user_dir = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)
local session_dir = user_dir..'/'..'li-session'
if Directory.Exists(session_dir) then
local files = Directory.GetFiles(session_dir,"*.lua")
for i = 1,files.Length do
list.Items:Add(Path.GetFileNameWithoutExtension(files[i-1]))
end
else
Directory.CreateDirectory(session_dir)
end
local function list_contains (name)
for i = 1,list.Items.Count do
if list.Items[i-1] == name then return true end
end
end
local function add_to_list (name)
list.Items:Add(name)
list.SelectedItem = name
current_name = name
end
local function session_file (name)
if not name then return end
return session_dir..'/'..name..'.lua'
end
local code = ConsoleTextBox() --RichTextBox()
code.Font = Font("Tahoma",10,FontStyle.Bold)
code.WordWrap = false
code:SetHandler(function(key)
if key == Keys.Tab then
code.SelectedText = " "
return true
end
return false
end)
local text = ConsoleTextBox() --RichTextBox()
text.Font = code.Font
text.WordWrap = false
-- please note that you must explicitly return false, since LuaInterface is
-- expecting a boolean return value!
text:SetHandler(function(key)
if key == Keys.Up then
get_history(true)
return true
elseif key == Keys.Down then
get_history(false)
return true
end
return false
end)
local function write (s)
text:AppendText(s)
end
list.SelectedIndexChanged:Add(function()
local file = session_file(list.SelectedItem)
if not file or not File.Exists(file) then return end
local txt = readfile(file)
if not txt then
ShowError ("Cannot open '"..file.."'")
return
end
code.Text = txt
end)
local function load_lua_file (file)
local oldFun = fun
fun = function(file) end
local res,err = pcall(dofile,file)
if not res then -- we have an error!
ShowError(err)
print(err)
end
fun = oldFun
end
local function load_lua ()
local dlg = OpenFileDialog()
dlg.Filter = "Lua (*.lua)|*.lua"
dlg.InitialDirectory = this_dir
if dlg:ShowDialog() == DialogResult.OK then
load_lua_file(dlg.FileName)
end
end
local function save_session ()
local dlg = SaveFileDialog()
dlg.Filter = "Lua (*.lua)|*.lua"
dlg.InitialDirectory = this_dir
if dlg:ShowDialog() ~= DialogResult.OK then return end
local f = io.open(dlg.FileName,"w")
f:write(table.concat(lines,'\n'))
f:close()
end
function clear_code ()
code:Clear()
no_name = true
end
function delete_list_item ()
local path = session_file(list.SelectedItem)
os.remove(path)
list.Items:Remove(list.SelectedItem)
clear_code()
end
function save_code ()
local file
if code.Lines.Length == 0 then return end
if not no_name then
file = list.SelectedItem
else -- no name has been assigned, after clearing the code pane
-- try make up an appropriate one!
local firstline = code.Lines[0]
local comment = firstline:match('%s*%-%-%s*(.*)')
if comment then file = comment
else file = "[current]" end
no_name = false
end
local path = session_file(file)
writefile(path,code.Text)
if not list_contains(file) then
add_to_list(file)
else
list.SelectedItem = file
end
return path
end
local function save_text ()
local dlg = SaveFileDialog()
dlg.Filter = "Text (*.txt)|*.txt"
dlg.InitialDirectory = this_dir
if dlg:ShowDialog() ~= DialogResult.OK then return end
writefile(dlg.FileName,text.Text)
end
local function save_and_go ()
local file = save_code()
if not file then return end
local res,err = pcall(dofile,file)
--ferr:write(file,'\n')
if not res then
local i1,i2,line = err:find(':(%d+):')
if i1 then
print(err:sub(i2+1))
write '\n> '
code:Focus()
select_line(code,tonumber(line)-1)
return
end
end
write '\n> '
append(lines,'dofile[['..file..']]')
text:Focus()
end
function fun (fn)
if not fn then -- prompt for a function name
fn = PromptForString("Lua Interface Console","Function name","")
if not fn then return end
end
if list_contains(fn) then
ShowError("'"..fn.."' already exists. Pick another name")
return
end
no_name = false
local txt = "function "..fn.."( )\n\nend\n"
code.Text = txt
add_to_list(fn)
code:Focus()
end
---------------------- Main Menu --------------------------------------
local menu = main_menu {
"File",{
"Load Lua(CtrlO)",load_lua,
"Save Session(CtrlS)",save_session,
"Save As Text",save_text,
"E&xit(CtrlX)",function() os.exit(0) end,
},
"Run",{
"Save and Go(F5)",save_and_go,
"Create Function",function() fun() end,
"Delete Item",delete_list_item,
"Clear Code Pane",clear_code,
},
"History", {
"Last(AltUpArrow)", function() get_history(true) end,
"Previous(AltDownArrow)", function() get_history(false) end
}
}
local function method (obj,fun)
return function()
fun(obj)
end
end
local popup = popup_menu {
"Copy",method(text,text.Copy),
"Paste",method(text,text.Paste),
"Cut",method(text,text.Cut),
}
------------ Managing Command History -----------
local help_idx = 1
function get_history (up)
call_later(function()
local delta
-- awful hack, cancelling out the last up/down arrow movement!
if up then
delta = -1
else
delta = 1
end
key_sent = true
call_later(function()
help_idx = help_idx + delta
local txt = lines[help_idx]
if not txt then
help_idx = help_idx - delta
return
end
select_line(text)
text.SelectedText = '> '..txt
end)
end)
end
------------ Special Key Handling ------------------
local lastLine = -1
text.KeyDown:Add(function(sender,args)
if args.KeyCode == Keys.Enter then
local lineNo = text:GetLineFromCharIndex(text.SelectionStart)
if lineNo ~= lastLine then -- for some reason, happens twice!
if lineNo >= text.Lines.Length then
lineNo = text.Lines.Length - 1
--ferr:write(lineNo,' ',text.Lines.Length,' goofed\n')
end
do
local line = text.Lines[lineNo]
line = line:gsub('^> ','')
lastLine = lineNo
call_later(function()
eval_lua(line)
append(lines,line)
help_idx = #lines + 1
write '> '
end)
end
end
end
end)
----------------------- Ouput Redirection ---------------------------------
function write_out (expand,...)
local t = {...}
local n = #t - 1
for i = 1,n do
write(tostring(t[i]))
if expand then write '\t' end
end
write(tostring(t[n+1]))
end
function writer (...)
write_out(false,...)
end
ilua.set_writer(writer)
function print (...)
write_out(true,...)
write '\r\n'
end
-------- Layout Controls ---------------------------------------------
local form = Form()
form.Menu = menu
form.Text = "LuaInterface GUI Prompt"
form.Size = Size(500,500)
form.Closing:Add(function()
os.exit(0)
end)
local panel = Panel()
panel.Dock = DockStyle.Top
local hsplitter = Splitter()
hsplitter.Dock = DockStyle.Left
hsplitter.MinSize = 70
code.Dock = DockStyle.Fill
code.Height = 70
list.Dock = DockStyle.Left
list.Width = 70
panel.Controls:Add(code)
panel.Controls:Add(hsplitter)
panel.Controls:Add(list)
-- note the particular order!
local splitter = Splitter()
splitter.Dock = DockStyle.Top
splitter.MinSize = 70
splitter.MinExtra = 100
text.Dock = DockStyle.Fill
text.ContextMenu = popup
form.Controls:Add(text)
form.Controls:Add(splitter)
form.Controls:Add(panel)
-- stuff exported to the interactive console
gettype = luanet.import_type
app = {code=code,text=text, list=list, form=form}
function cd (path)
if not path or #path == 0 then
print(Directory.GetCurrentDirectory())
else
Directory.SetCurrentDirectory(path)
end
end
write 'Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio\r\n'
write '> '
if arg[1] and File.Exists(arg[1]) then
load_lua_file(arg[1])
end
text.WordWrap = true
console = text
form:ShowDialog()
---- A simple interactive Console for LuaInterface using Gtk#
require 'CLRPackage'
import ('gtk-sharp','Gtk')
luanet.load_assembly 'gdk-sharp'
luanet.load_assembly 'glib-sharp'
local Gdk = luanet.namespace 'Gdk'
local Glib = luanet.namespace 'GLib'
local ferr = io.stderr -- for debugging
--~ Glib.ExceptionManager.UnhandledException:Add(function(ex,what)
--~ ferr:write(tostring(ex),' ',tostring(what),'\n')
--~ ex.ExitApplication = false
--~ end)
local Up, Down, Return = Gdk.Key.Up, Gdk.Key.Down, Gdk.Key.Return
Application.Init()
local win = Window("Gtk# Lua")
win.DeleteEvent:Add(function()
Application.Quit()
end)
win:Resize(500,500)
local buffer
local history = {idx=1}
function add_history(line)
if line ~= history[#history] then
table.insert(history,line)
history.idx = #history + 1
end
end
local function clamp(i,s,n)
if i < s then return 1
elseif i > n then return n
else return i
end
end
function line_range(lno)
lno = lno or buffer.LineCount - 1
local start = buffer:GetIterAtLine(lno-1)
local endi = buffer:GetIterAtLine(lno)
return start,endi
end
local function set_last_line(text)
if not text then return end
local start = buffer:GetIterAtLine(buffer.LineCount-1)
local endi = buffer.EndIter
start = buffer:Delete(start,endi)
buffer:Insert(start,'> '..text)
end
-- we need to subclass Gtk.TextView, since we want to trap
-- the up and down keys for accessing command history
local edit = {}
function edit:OnKeyPressEvent(event)
local key = event.Key
if key == Up or key == Down then
local delta
if key == Down then
delta = 1
else
delta = -1
end
history.idx = clamp(history.idx + delta,1,#history)
set_last_line(history[history.idx])
return true
else
return self.base:OnKeyPressEvent(event)
end
end
luanet.make_object(edit,'Gtk.TextView')
buffer = edit.Buffer
local function create_tag(colour)
local tag = TextTag(colour)
tag.Foreground = colour
buffer.TagTable:Add(tag)
return {tag}
end
local plain,err_style = create_tag "#00F" , create_tag "#F00"
function write(txt,tag)
tag = tag or plain
buffer:InsertWithTags(buffer.EndIter,txt,tag)
end
local prompt = '> '
write 'Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio\n'
write(prompt)
function print(...)
local args,n = {...},select('#',...)
for i = 1,n do
write(tostring(args[i])..'\t')
end
write '\n'
end
local function collect(ok,...)
local args = {...}
args.n = select('#',...)
return ok, args
end
function eval(s)
if s == 'quit' then Application.Quit() end
local expr = s:match('^%s*=%s+(.+)')
if expr then s = 'return '..expr end
local chunk,err = loadstring(s,'tmp')
local ok,res
if chunk then
ok,res = collect(pcall(chunk))
if not ok then err = res[1] end
end
if err then
write(tostring(err)..'\n',err_style)
elseif res.n > 0 then
print(unpack(res,1,res.n))
_G._ = res[1] -- last expression put into underscore global
end
end
edit.KeyReleaseEvent:Add(function(obj,e)
local event = e.Event
if event.Key == Return then
local start,endi = line_range()
local stmt = start:GetText(endi)
local i1,i2 = stmt:find(prompt,1,true)
if i1 == 1 then
stmt = stmt:sub(i2+1)
end
stmt = stmt:gsub('\n$','')
eval(stmt)
add_history(stmt)
buffer:InsertAtCursor(prompt)
end
end)
local sbox = ScrolledWindow()
sbox.VscrollbarPolicy = PolicyType.Always
sbox:Add(edit)
win:Add(sbox)
win:ShowAll()
Application.Run()
-- lua.lua - Lua 5.1 interpreter (lua.c) reimplemented in Lua.
--
-- WARNING: This is not completed but was quickly done just an experiment.
-- Fix omissions/bugs and test if you want to use this in production.
-- Particularly pay attention to error handling.
--
-- (c) David Manura, 2008-08
-- Licensed under the same terms as Lua itself.
-- Based on lua.c from Lua 5.1.3.
-- Improvements by Shmuel Zeigerman.
-- Variables analogous to those in luaconf.h
local LUA_INIT = "LUA_INIT"
local LUA_PROGNAME = "lua"
local LUA_PROMPT = "> "
local LUA_PROMPT2 = ">> "
local function LUA_QL(x) return "'" .. x .. "'" end
local lua51 = _VERSION:match '5%.1$'
-- Variables analogous to those in lua.h
local LUA_RELEASE, LUA_COPYRIGHT, eof_ender
if lua51 then
LUA_RELEASE = "Lua 5.1.4"
LUA_COPYRIGHT = "Copyright (C) 1994-2008 Lua.org, PUC-Rio"
eof_ender = LUA_QL("<eof>")
else
LUA_RELEASE = "Lua 5.2.0"
LUA_COPYRIGHT = "Copyright (C) 1994-2011 Lua.org, PUC-Rio"
eof_ender = '<eof>'
end
local EXTRA_COPYRIGHT = "lua.lua (c) David Manura, 2008-08"
-- Note: don't allow user scripts to change implementation.
-- Check for globals with "cat lua.lua | luac -p -l - | grep ETGLOBAL"
local _G = _G
local assert = assert
local collectgarbage = collectgarbage
local loadfile = loadfile
local loadstring = loadstring or load
local pcall = pcall
local rawget = rawget
local select = select
local tostring = tostring
local type = type
local unpack = unpack or table.unpack
local xpcall = xpcall
local io_stderr = io.stderr
local io_stdout = io.stdout
local io_stdin = io.stdin
local string_format = string.format
local string_sub = string.sub
local os_getenv = os.getenv
local os_exit = os.exit
local progname = LUA_PROGNAME
-- Use external functions, if available
local lua_stdin_is_tty = function() return true end
local setsignal = function() end
local function print_usage()
io_stderr:write(string_format(
"usage: %s [options] [script [args]].\n" ..
"Available options are:\n" ..
" -e stat execute string " .. LUA_QL("stat") .. "\n" ..
" -l name require library " .. LUA_QL("name") .. "\n" ..
" -i enter interactive mode after executing " ..
LUA_QL("script") .. "\n" ..
" -v show version information\n" ..
" -- stop handling options\n" ..
" - execute stdin and stop handling options\n"
,
progname))
io_stderr:flush()
end
local our_tostring = tostring
local tuple = table.pack or function(...)
return {n=select('#', ...), ...}
end
local using_lsh,lsh
local function our_print (...)
local args = tuple(...)
for i = 1,args.n do
io.write(our_tostring(args[i]),'\t')
end
_G._ = args[1]
io.write '\n'
end
local function saveline(s)
if using_lsh then
lsh.saveline(s)
end
end
local function getline(prmt)
if using_lsh then
return lsh.readline(prmt)
else
io_stdout:write(prmt)
io_stdout:flush()
return io_stdin:read'*l'
end
end
local function l_message (pname, msg)
if pname then io_stderr:write(string_format("%s: ", pname)) end
io_stderr:write(string_format("%s\n", msg))
io_stderr:flush()
end
local function report(status, msg)
if not status and msg ~= nil then
msg = tostring(msg)
--~ msg = (type(msg) == 'string' or type(msg) == 'number') and tostring(msg)
--~ or "(error object is not a string)"
l_message(progname, msg);
end
return status
end
local function traceback (message)
local tp = type(message)
if tp ~= "string" and tp ~= "number" then return message end
local debug = _G.debug
if type(debug) ~= "table" then return message end
local tb = debug.traceback
if type(tb) ~= "function" then return message end
return tb(message, 2)
end
local function docall(f, ...)
local tp = {...} -- no need in tuple (string arguments only)
local F = function() return f(unpack(tp)) end
setsignal(true)
local result = tuple(xpcall(F, traceback))
setsignal(false)
-- force a complete garbage collection in case of errors
if not result[1] then collectgarbage("collect") end
return unpack(result, 1, result.n)
end
function dofile(name)
local f, msg = loadfile(name)
if f then f, msg = docall(f) end
return report(f, msg)
end
local function dostring(s, name)
local f, msg = loadstring(s, name)
if f then f, msg = docall(f) end
return report(f, msg)
end
local function dolibrary (name)
return report(docall(_G.require, name))
end
local function print_version()
l_message(nil, LUA_RELEASE .. " " .. LUA_COPYRIGHT.."\n"..EXTRA_COPYRIGHT)
end
local function getargs (argv, n)
local arg = {}
for i=1,#argv do arg[i - n] = argv[i] end
if _G.arg then
local i = 0
while _G.arg[i] do
arg[i - n] = _G.arg[i]
i = i - 1
end
end
return arg
end
local function get_prompt (firstline)
-- use rawget to play fine with require 'strict'
local pmt = rawget(_G, firstline and "_PROMPT" or "_PROMPT2")
local tp = type(pmt)
if tp == "string" or tp == "number" then
return tostring(pmt)
end
return firstline and LUA_PROMPT or LUA_PROMPT2
end
local function fetchline(firstline)
return getline(get_prompt(firstline))
end
local function incomplete (msg)
if msg then
if string_sub(msg, -#eof_ender) == eof_ender then
return true
end
end
return false
end
local function pushline (firstline)
local fine,b = true
repeat
b = fetchline(firstline)
if not b then return end -- no input
if using_lsh then
fine = lsh.checkline(b)
end
until fine
if firstline and string_sub(b, 1, 1) == '=' then
return "return " .. string_sub(b, 2) -- change '=' to `return'
else
return b
end
end
local function loadline ()
local b = pushline(true)
if not b then return -1 end -- no input
local f, msg
while true do -- repeat until gets a complete line
f, msg = loadstring(b, "=stdin")
if not incomplete(msg) then break end -- cannot try to add lines?
local b2 = pushline(false)
if not b2 then -- no more input?
return -1
end
b = b .. "\n" .. b2 -- join them
end
saveline(b)
return f, msg
end
local function dotty ()
local oldprogname = progname
progname = nil
using_lsh,lsh = false -- pcall(require, 'luaish') blows with LI ??
if using_lsh then
our_tostring = lsh.tostring
else
--print('problem loading luaish:',lsh)
our_tostring = tostring
end
while true do
local result
local status, msg = loadline()
if status == -1 then break end
if status then
result = tuple(docall(status))
status, msg = result[1], result[2]
end
report(status, msg)
if status and result.n > 1 then -- any result to print?
status, msg = pcall(our_print, unpack(result, 2, result.n))
if not status then
l_message(progname, string_format(
"error calling %s (%s)",
LUA_QL("print"), msg))
end
end
end
io_stdout:write"\n"
io_stdout:flush()
progname = oldprogname
end
local function handle_script(argv, n)
_G.arg = getargs(argv, n) -- collect arguments
local fname = argv[n]
if fname == "-" and argv[n-1] ~= "--" then
fname = nil -- stdin
end
local status, msg = loadfile(fname)
if status then
status, msg = docall(status, unpack(_G.arg))
end
return report(status, msg)
end
local function collectargs (argv, p)
local i = 1
while i <= #argv do
if string_sub(argv[i], 1, 1) ~= '-' then -- not an option?
return i
end
local prefix = string_sub(argv[i], 1, 2)
if prefix == '--' then
if #argv[i] > 2 then return -1 end
return argv[i+1] and i+1 or 0
elseif prefix == '-' then
return i
elseif prefix == '-i' then
if #argv[i] > 2 then return -1 end
p.i = true
p.v = true
elseif prefix == '-v' then
if #argv[i] > 2 then return -1 end
p.v = true
elseif prefix == '-e' then
p.e = true
if #argv[i] == 2 then
i = i + 1
if argv[i] == nil then return -1 end
end
elseif prefix == '-l' then
if #argv[i] == 2 then
i = i + 1
if argv[i] == nil then return -1 end
end
else
return -1 -- invalid option
end
i = i + 1
end
return 0
end
local function runargs(argv, n)
local i = 1
while i <= n do if argv[i] then
assert(string_sub(argv[i], 1, 1) == '-')
local c = string_sub(argv[i], 2, 2) -- option
if c == 'e' then
local chunk = string_sub(argv[i], 3)
if chunk == '' then i = i + 1; chunk = argv[i] end
assert(chunk)
if not dostring(chunk, "=(command line)") then return false end
elseif c == 'l' then
local filename = string_sub(argv[i], 3)
if filename == '' then i = i + 1; filename = argv[i] end
assert(filename)
if not dolibrary(filename) then return false end
end
i = i + 1
end end
return true
end
local function handle_luainit()
local init = os_getenv(LUA_INIT)
if init == nil then
return -- status OK
elseif string_sub(init, 1, 1) == '@' then
dofile(string_sub(init, 2))
else
dostring(init, "=" .. LUA_INIT)
end
end
local import_ = _G.import
if import_ then
lua_stdin_is_tty = import_.lua_stdin_is_tty or lua_stdin_is_tty
setsignal = import_.setsignal or setsignal
LUA_RELEASE = import_.LUA_RELEASE or LUA_RELEASE
LUA_COPYRIGHT = import_.LUA_COPYRIGHT or LUA_COPYRIGHT
_G.import = nil
end
if _G.arg and _G.arg[0] and #_G.arg[0] > 0 then progname = _G.arg[0] end
local argv = {...}
handle_luainit()
local has = {i=false, v=false, e=false}
local script = collectargs(argv, has)
if script < 0 then -- invalid args?
print_usage()
os_exit(1)
end
if has.v then print_version() end
local status = runargs(argv, (script > 0) and script-1 or #argv)
if not status then os_exit(1) end
if script ~= 0 then
status = handle_script(argv, script)
if not status then os_exit(1) end
else
_G.arg = nil
end
if has.i then
dotty()
elseif script == 0 and not has.e and not has.v then
if lua_stdin_is_tty() then
print_version()
require 'CLRPackage'
import 'System'
dotty()
else dofile(nil) -- executes stdin as a file
end
end
require 'com'
-- http://ss64.com/vb/filesystemobject.html
fo = com.CreateObject("Scripting.FileSystemObject")
each = luanet.each
print(fo:FileExists 'com.lua')
print 'and'
f = fo:GetFile 'com.lua'
print (f.Name)
drives = fo.Drives
print(drives.Count)
print(drives)
-- this is weird: can access as property!
ee = drives.GetEnumerator
while ee:MoveNext() do
-- have to wrap this COM object explicitly!
local drive = com.wrap(ee.Current)
print(drive.DriveLetter)
end
function com.each(obj)
local e = obj.GetEnumerator
return function()
if e:MoveNext() then
return com.wrap(e.Current)
end
end
end
for d in com.each(drives) do print(d.DriveType) end
--print(fo.Drives['C'])
print(fo:FolderExists 'lua')
print(fo:GetAbsolutePathName 'lua')
this = fo:GetFolder '..'
for f in com.each(this.SubFolders) do print(f.Name) end
--~ drive = fo:Drives 'C'
--~ print(drive.AvailableSpace)
...@@ -1816,6 +1816,17 @@ namespace NLuaTest ...@@ -1816,6 +1816,17 @@ namespace NLuaTest
lua.DoString ("test:Print('this will pass')"); lua.DoString ("test:Print('this will pass')");
lua.DoString ("test:Print('this will ','fail')"); lua.DoString ("test:Print('this will ','fail')");
} }
}
[Test]
public void TestCtype ()
{
using (Lua lua = new Lua ()) {
lua.LoadCLRPackage ();
lua.DoString ("import'System'");
var x = lua.DoString ("return luanet.ctype(String)")[0];
Assert.AreEqual (x, typeof(String), "#1 String ctype test");
}
} }
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment