if var then cfg[var] = val else table.insert (cfg.inputs, a) end
end
--- metalua.mlc doesn't exit yet; this preload manager loads a mockup which is just
+-- metalua.mlc doesn't exist yet; this preload manager loads a mockup which is just
-- sufficient to compile the real mlc.mlua
package.preload['metalua.mlc'] = function()
e=p[i]
if type(e) == "string" then
if not lx:is_keyword (lx:next(), e) then
- parse_error (lx, "Keyword '%s' expected", e) end
+ parse_error (lx, "A keyword was expected, probably `%s'.", e) end
elseif is_parser (e) then
table.insert (r, e (lx))
else
- gg.parse_error (lx,"Sequence `%s': element #%i is not a string "..
+ gg.parse_error (lx,"Sequence `%s': element #%i is neither a string "..
"nor a parser: %s",
p.name, i, table.tostring(e))
end
elseif type(p[1])=="string" then -- find name based on 1st keyword
if #p==1 then p.name=p[1]
elseif type(p[#p])=="string" then
- p.name = p[1] .. " ... " . p[#p]
+ p.name = p[1] .. " ... " .. p[#p]
else p.name = p[1] .. " ..." end
else -- can't find a decent name
p.name = "<anonymous>"
-- Check for non-associative operators, and complain if applicable.
-----------------------------------------
elseif p2.assoc=="none" and p2.prec==prec then
- parser_error (lx, "non-associative operator!")
+ parse_error (lx, "non-associative operator!")
-----------------------------------------
-- No infix operator suitable at that precedence
compiler should be prefixed with an option flag, hinting what must be
done with them: take tham as file names to compile, as library names
to load, as parameters passed to the running program... When option
-flags lack, metalua tries to adopt a "Do What I Mean" approach:
+flags are absent, metalua tries to adopt a "Do What I Mean" approach:
- if no code (no library, no literal expression and no file) is
specified, the first flag-less parameter is taken as a file name to
function id_or_literal (lx)
local a = lx:next()
if a.tag~="Id" and a.tag~="String" and a.tag~="Number" then
- gg.parse_error (lx, "Unexpected expr token %s",
- _G.table.tostring (a, 'nohash'))
+ local msg
+ if a.tag=='Eof' then
+ msg = "End of file reached when an expression was expected"
+ elseif a.tag=='Keyword' then
+ msg = "An expression was expected, and `"..a[1]..
+ "' can't start an expression"
+ else
+ msg = "Unexpected expr token " .. _G.table.tostring (a, 'nohash')
+ end
+ gg.parse_error (lx, msg)
end
return a
end
-- That is, without sugar:
return {tag="String", {tag="Index", {tag="Splice", id[1] },
{tag="Number", 1 } } }
- else error ("Identifier expected: "..table.tostring(id)) end
+ else error ("Identifier expected: ".._G.table.tostring(id, 'nohash')) end
end
--------------------------------------------------------------------------------
else
assert (#e > 0)
if #e > 1 then
- gg.parse_error (lx, "comma is not a valid statement separator") end
+ gg.parse_error (lx,
+ "comma is not a valid statement separator; statement can be "..
+ "separated by semicolons, or not separated at all") end
if e[1].tag ~= "Call" and e[1].tag ~= "Invoke" then
- gg.parse_error (lx, "This expression is of type '%s'; "..
- "only function and method calls make valid statements",
- e[1].tag or "<list>")
+ local typename
+ if e[1].tag == 'Id' then
+ typename = '("'..e[1][1]..'") is an identifier'
+ elseif e[1].tag == 'Op' then
+ typename = "is an arithmetic operation"
+ else typename = "is of type '"..(e[1].tag or "<list>").."'" end
+
+ gg.parse_error (lx, "This expression " .. typename ..
+ "; a statement was expected, and only function and method call "..
+ "expressions can be used as statements");
end
return e[1]
end
-- anywhere or assigned to inside a function.
--
+local getinfo, error, rawset, rawget = debug.getinfo, error, rawset, rawget
+
local mt = getmetatable(_G)
if mt == nil then
mt = {}
setmetatable(_G, mt)
end
-__STRICT = true
+__strict = true
mt.__declared = {}
+local function what ()
+ local d = getinfo(3, "S")
+ return d and d.what or "C"
+end
+
mt.__newindex = function (t, n, v)
- if __STRICT and not mt.__declared[n] then
- local w = debug.getinfo(2, "S").what
+ if __strict and not mt.__declared[n] then
+ local w = what()
if w ~= "main" and w ~= "C" then
error("assign to undeclared variable '"..n.."'", 2)
end
end
mt.__index = function (t, n)
- if not mt.__declared[n] and debug.getinfo(2, "S").what ~= "C" then
+ if __strict and not mt.__declared[n] and what() ~= "C" then
error("variable '"..n.."' is not declared", 2)
end
return rawget(t, n)
# Upon installation, everything will be moved to ${INSTALL_LIB} and ${INSTALL_BIN}
if [ -z "${BUILD}" ]; then
- BUILD=/tmp/metalua-build
+ BUILD=$(mkdir -p ../build; cd ../build; pwd)
fi
if [ -z "${BUILD_BIN}" ]; then