[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: compile-time globals
- From: David Manura <dm.lua@...>
- Date: Tue, 21 Aug 2007 04:32:21 +0000 (UTC)
Thomas Lauer <thomas.lauer <at> virgin.net> writes:
> ...I experimented with an extension to the parser to
> enable the declaration of globals at compile time, similar to what the
> local keyword does for local variables....
> However, I've run into a problem ...module() is a runtime feature and
> the compiler knows nothing about it
True, require/module will need to be a compile time construct.
I've updated LuaFish[1] (which was recently announced on this list) to do
something like this. Again, it's quite preliminary, but one of the included
examples is shown below.
First, a simple module is defined as follows:
<snip>
-- msquare.lua
local M = {}; M.__index = M
function M.create(length)
local self = setmetatable({length = length}, M)
return self
end
local function area(self) return self.length^2 end
M.area = area
local function perimeter(self) return self.length * 4 end
M.perimeter = perimeter
local function setcolor(self, color)
SETTYPE(color, 'string') -- static type check argument
self.color = color
end
M.setcolor = setcolor
-- The function inside the ONCOMPILE macro is executed at
-- compile time.
ONCOMPILE(function(scope) -- scope is a table of references to the
-- AST's of lexicals at the current
-- code location
-- Static type definition of the class.
local class = {}
class.area = scope.area -- use static function signatures
class.perimeter = scope.perimeter
class.setcolor = scope.setcolor
registerclass('Square', class)
end)
return M
</snip>
The function in the "ONCOMPILE" macro gets executed at what is effectively
compile time. This particular function builds a table of method names and their
signatures, which makes up the static type of a class that we register.
Next, another Lua program uses that module as follows:
<snip>
-- module_usage_m.lua
-- demonstrates static checking of class methods.
-- The function inside the ONCOMPILE macro is executed at
-- compile time.
ONCOMPILE(function()
-- load type definitions at compile time to allow
-- compile-time type checking.
mrequire 'square_m'
end)
print 'begin'
local mrequire = require 'LuaFish.macro'.require
local Square = mrequire 'square_m'
local m = Square.create(5)
SETTYPE(m, 'Square') -- bind a static type to the lexical
assert(m:area() == 25) -- ok
assert(m:perimeter() == 20) -- ok
m:setcolor('blue') -- ok
-- this gives compile-time error:
-- "method volume absent in class Square"
-- print(m:volume())
-- this gives compile-time error:
-- "argument color type is number but expecting string"
-- m:setcolor(5)
print 'done'
</snip>
Doing the require inside the "ONCOMPILE" macro causes the types and method names
to be loaded at compile time. These types are then bound to a lexical at
compile time via the SETTYPE macro. This then permits compile-time detection of
the errors noted in the commented code at the end.
The ONCOMPILE macro is actually similar to the "BEGIN" block in Perl. Putting a
require inside an ONCOMPILE blocks is analogous to using a "use" [2] v.s.
"require" in Perl.
[1] LuaFish v. 0.2 - http://lua-users.org/wiki/LuaFish
[2] Perl "use" statement - http://perldoc.perl.org/functions/use.html