]> git.lizzy.rs Git - metalua.git/commitdiff
Final cleanup for v0.4, fix in win32 building script, merge with linux build process.
authorFabien Fleutot <fabien@macfabien.local>
Wed, 6 Feb 2008 22:10:13 +0000 (23:10 +0100)
committerFabien Fleutot <fabien@macfabien.local>
Wed, 6 Feb 2008 22:10:13 +0000 (23:10 +0100)
23 files changed:
.gitignore
INSTALL.TXT
README.TXT
doc/manual/data.tex
doc/manual/metalua-manual.pdf
src/Makefile
src/binlibs/Makefile
src/config
src/lib/autotable.lua [deleted file]
src/lib/extension/H-runtime.mlua
src/lib/extension/machine-runtime.mlua [deleted file]
src/lib/extension/machine.mlua [deleted file]
src/lib/extension/trycatch.mlua
src/lib/package2.lua
src/lib/srcdump.mlua [deleted file]
src/lua/luaconf.h
src/samples/fsm_test.mlua [deleted file]
src/samples/h_test.mlua
src/samples/h_test2.mlua
src/samples/ifexpr.mlua
src/samples/lex_switch_test.mlua
src/samples/walk_id_test.mlua
src/win32/make-win32-msvc.bat

index eafae09d33ddfd1d90ad6bfa746041b96e4f8360..9216ea7ba8fdab08f4b0f6080591005a608f65a4 100644 (file)
@@ -17,4 +17,5 @@ src/lua/lua
 src/compiler/bootstrap
 src/compiler/metalua
 junk
+patches
 ran
index 4166daf12453ec9a33817376321ac43566259319..048b3c96c744bffdd126d6dcaccb20c7942f344c 100644 (file)
@@ -1,9 +1,11 @@
 Installation guidelines
 =======================
 
-TESTING AN INSTALLATION PROCEDURE IS HARD, AND RARELY DONE RIGHT FROM
-THE FIRST TIME. IF YOU EXPERIENCE INSTALLATION TROUBLES, PLEASE REPORT
+======================================================================
+TESTING AN INSTALLATION PROCEDURE IS HARD, AND RARELY DONE RIGHT AT
+THE FIRST TRY. IF YOU EXPERIENCE INSTALLATION TROUBLES, PLEASE REPORT
 THEM, TO AVOID THEM TO FUTURE USERS. mailto:metalua@gmail.com
+======================================================================
 
 Prerequisites
 -------------
@@ -21,24 +23,14 @@ You need to:
 
 - edit metalua\src\win32\make-win32-msvc.bat, and set the
   user configuration:
-  - The directory where you want to put your libs and executables, 
+  * The directory where you want to put your libs and executables, 
     MUALIB_TARGET.
-  - The directory where the compiler and linker are,
+  * The directory where the compiler and linker are,
     MSVCDIR.
 
 - open a DOS shell in metalua\src, and run the batch file above:
   d:\fabien\src\metalua\src> win32\make-win32-msvc
 
-Notice that under windows, Pluto is linked statically with the Lua VM,
-as it exploits some APIs which are not exported as DLL by default. If
-you want to run your own Lua VM, you'll need either:
-- to set the LUA_MFAST environment variable so that the compiler won't
-  use Pluto; but then, interactions between compile-time parts of
-  files compiled together might sometimes cause troubles
-- or recompile your VM with Pluto linked in it
-- or recompile it by exporting the LUAI_FUNC functions as DLL entry
-  points. 
-
 - Set your environment variables. A script metalua\src\mlua_setenv.bat
   must have been generated, which contains the appropriate
   settings. If you want to commit these setting permanently, you'll
@@ -49,8 +41,8 @@ Mingw
 -----
 There is also a migw port, which hasn't been tested for a while and is
 likely to be broken. I'd be grateful if someone provided a patch for
-this. I've never tried to compile it under cygwin either,
-contributions are welcome.
+this. I've never tried to compile it under cygwin either, patches are
+welcome.
 
 Un*x
 ----
@@ -80,18 +72,23 @@ your .bashrc file.
 
 Troubleshooting:
 ----------------
-
 Under Linux, if you don't have readline and don't want to install it
 (e.g. you rely on rlwrap or ledit), you'll have to remove -lreadline
 from lua/Makefile, and to remove the #define LUA_USE_READLINE from
 lua/luaconf.h
 
 If you use your own Lua VM, depending on your OS, you might have
-problems with unexported symbols which are required by Pluto. Either
-link Pluto with statically with your VM (take inspiration from the
-win32 hack above), 
-
-
+problems with unexported symbols required by Pluto. Pluto requires the
+symbols prefixed with LUAI_FUNC in the VM to be exported, and they
+aren't by default under Linux and Windows. This is set in luaconf.h;
+you'll need to change that setting in your own Lua VM if you want to
+use it.
+
+Alternatively, you can let metalua run without Pluto by setting the
+environment variable LUA_MFAST to "yes". However, this might cause
+parasitic interactions when several source files are compiled
+simultaneously, so you'd rather precompile each file and library one
+by one.
 
 Test drive
 ----------
index 350409e77a7247ea462147899442d75e5d5c5fa6..bf819109ab12b456a616653a9f972708e4a30e76 100644 (file)
@@ -12,12 +12,13 @@ follows.
 
 Dynamic Parsers
 ---------------
-One of these tools is dynamic parser: a source file can change the
-syntax recognized by the parser while it's being parsed. Taken alone,
-this feature lets you make superficial syntax tweaks on the
-language. The parser is based on a parser combinator called 'gg'. You
-should know the half dozen functions in gg API to do advanced things,
-but it means you can use and define functions that transform parsers:
+
+One of the tools is the dynamic parser, which allows a source file to
+change the grammar recognized by the parser, while it's being
+parsed. Taken alone, this feature lets you make superficial syntax
+tweaks on the language. The parser is based on a parser combinator
+library called 'gg'; you should know the half dozen functions in gg
+API to do advanced things:
 
 - There are a couple of very simple combinators like gg.list,
   gg.sequence, qq.multisequence, gg.optkeyword etc. that offer a level
@@ -25,14 +26,17 @@ but it means you can use and define functions that transform parsers:
   mlp.expr parses Lua expressions, gg.list{ mlp.expr } creates a
   parser which handles lists of Lua expressions.
 
-- Since you can create all the combinators you can think of, there
-  also are combinators specialized for typical language tasks. In
-  Yacc-like systems, the language definition quickly becomes
-  unreadable, because all non-native features have to be encoded in
-  clumsy and brittle ways; so if your parser won't natively let you
-  specify infix operator precedence and associativity easily, tough
-  luck for you and your code maintainers. With combinators, this is
-  abstracted away in a regular function, so you just write:
+- Since you can create all the combinators you can think of (they're
+  regular, higher-order functions), there also are combinators
+  specialized for typical language tasks. In Yacc-like systems, the
+  language definition quickly becomes unreadable, because all
+  non-native features have to be encoded in clumsy and brittle ways.
+  So if your parser won't natively let you specify infix operator
+  precedence and associativity easily, tough luck for you and your
+  code maintainers. With combinators OTOH, most of such useful
+  functions already exist, and you can write your owns without
+  rewriting the parser itself. For instance, adding an infix operator
+  would just look like:
 
   > mlp.expr.infix:add{ "xor", prec=40, assoc='left', builder=xor_builder }
 
@@ -42,23 +46,26 @@ but it means you can use and define functions that transform parsers:
   compiling a valid one, for a use=able compiler.
 
 Yacc-like systems might seem simpler to adopt than combinators, as
-long as they're used on extremely simple problems. However, if if you
+long as they're used on extremely simple problems. However, if you
 either try to write something non trivial, or to write a simple macro
 in a robust way, you'll need to use lots of messy tricks and hacks,
-and spend much more time getting them (seemingly) ritght than that 1/2
-hour required to master most of gg.
+and spend much more time getting them (approximatively) right than
+that 1/2 hour required to master the regular features of gg.
 
 
 Real meta-programming
 ---------------------
+
 If you plan to go beyond trivial keyword-for-keyword syntax tweaks,
-what will limit you is the ability to manipulate source code
-conveniently: without the proper tools and abstractions, even the
-simplest tasks will turn into a dirty hacks fest, then either into a
-nightmare, or most often into abandonware. Providing an empowering
-framework is metalua's whole purpose.  The core principle is that
-programs prefer to manipulate code as trees (whereas most developers
-prefer ASCII sources). The make-or-break deal is then:
+what will limit you is not syntax definition, but the ability to
+manipulate source code conveniently: without the proper tools and
+abstractions, even the simplest tasks will turn into a dirty hacks
+fest, then either into a maintenance nightmare, or simply into
+abandonware. Providing an empowering framework so that you don't get
+stuck in such predicaments is metalua's whole purpose.  The central
+concept is that programs prefer to manipulate code as trees, whereas
+most developers prefer ASCII sources, so both representations must be
+freely interchangeable. The make-or-break deal is then:
 
 - To easily let users see sources as trees, as sources, or as
   combination thereof, and switch representations seamlessly.
@@ -82,8 +89,8 @@ Library-wise, metalua offers a set of syntax tree manipulation tools:
   compiler-writing specialized languages (and which has nothing to do
   with string regular expressions BTW), which lets you express
   advanced tree analysis operations in a compact, readable and
-  efficient way.  If you regularly have to work with advanced data
-  structures and you try it, you'll never go back.
+  efficient way.  If you have to work with advanced data structures
+  and you try it, you'll never go back.
 
 - The walker library allows you to perform transformations on big
   portions of programs. It lets you easily express things like:
@@ -91,9 +98,9 @@ Library-wise, metalua offers a set of syntax tree manipulation tools:
   error statements", "rename all local variables and their instances
   into unique fresh names", "list the variables which escape this
   chunk's scope", "insert a type-checking instruction into every
-  assignments to variable X", etc. You can't write many non-trivial
-  macros without needing to do some of those global code
-  transformations.
+  assignments to variable X", etc. Most of non-trivial macros will
+  requir some of those global code transformations, if you really want
+  them to behave correctly.
 
 - Macro hygiene, although not perfect yet in metalua, is required if
   you want to make macro writing reasonably usable (and contrary to a
@@ -119,9 +126,9 @@ Notworthy changes since 0.3
 
 
 - The compiler/interpreter front-end is completely rewritten. The new
-  program, aptly named 'metalua', supports proper passing of arguments
-  to programs, and is generally speaking much more user friendly than
-  the mlc from the previous version.
+  frontend program, aptly named 'metalua', supports proper passing of
+  arguments to programs, and is generally speaking much more user
+  friendly than the mlc from the previous version.
 
 
 - Metalua source libraries are looked for in environmemt variable
@@ -130,8 +137,8 @@ Notworthy changes since 0.3
   native Lua compiler.
 
   By convention, metalua source files should have extension .mlua. By
-  default, bytecode and plain lua files are preferred to metalua
-  sources, which lets you easily precompile your libraries.
+  default, bytecode and plain lua files have higher precedence than
+  metalua sources, which lets you easily precompile your libraries.
 
 
 - Compilation of files are separated in different Lua Rings: this
@@ -156,30 +163,34 @@ Notworthy changes since 0.3
   include:
   - Lua Rings and Pluto, duct-taped together into Springs, an improved
     Rings that lets states exchange arbitrary data instead of just
-    scalars and strings.
+    scalars and strings. Since Pluto requires a (minor) patch to the
+    VM, it can be disabled.
   - Lua bits for bytecode dumping.
   - As always, very large amounts of code borrowed from Yueliang.
   - As a commodity, I've also packaged Lua sources in.
 
 
+- Extensions to Lua standard libraries: many more features in table
+  and the baselib, a couple of string features, and a package system
+  which correctly handles metalua source files.
+
+
 - Builds on Linux, OSX, Microsoft Visual Studio. Might build on mingw
-  (not tested recently). It's easily ported to all systems with a full
-  support for lua.
-
-  The MS-windows building is hackish: it's driven by a batch script,
-  and Pluto can't compile as a win32 DLL, so it's linked in the Lua
-  VM. If you want to run your own VM, either link pluto in statically,
-  or disabled separate compilation by setting environment variable
-  LUA_MFAST at true. In the later case, expect puzzling behaviors when
-  you load several sources containing compile-time code (==>
-  precompile everything).
-
-  Notice that bits of the compiler itself are now written in metalua,
+  (not tested recently, patches welcome). It's easily ported to all
+  systems with a full support for lua, and if possible dynamic
+  libraries.
+
+  The MS-windows building is based on a dirty .bat script, because
+  that's pretty much the only thing you're sure to find on a win32
+  computer. It uses Microsoft Visual Studio as a compiler (tested with
+  VC++ 6).
+
+  Notice that parts of the compiler itself are now written in metalua,
   which means that its building now goes through a bootstrapping
   stage.
 
 
-- Structural pattern matching:
+- Structural pattern matching improvements:
   - now also handles string regular expressions: 'someregexp'/pattern
     will match if the tested term is a string accepted by the regexp,
     and on success, the list of captures done by the regexp is matched
@@ -216,7 +227,7 @@ Notworthy changes since 0.3
  
 - Overhaul of the code walking library:
   - the API has been simplified: the fancy predicates proved more
-    cumbersome to use than a bit pattern matching in the visitors
+    cumbersome to use than a bit of pattern matching in the visitors.
   - binding identifiers are handled as a distinct AST class
   - walk.id is scope-aware, handles free and bound variables in a
     sensible way.
@@ -228,21 +239,23 @@ Notworthy changes since 0.3
   macro system with v0.4, but what exists remains a work in
   progress. Lua is a Lisp-1, which means unhygienic macros are very
   dangerous, and hygiene a la Scheme pretty much limits macro writing
-  to a term rewriting subset of the language, which is crippling to
-  use. 
-
-  Note: inside hygiene, i.e. local variables created by the macro
-  which might capture user's variable instances, is trivial to address
-  by alpha conversion. The trickier part is outside hygiene, when
-  user's binders capture globals required by the macro-generated
-  code. That's the cause of pretty puzzling and hard to find bugs. And
-  the *really* tricky part, which is still unsolved in metalua, is
-  when you have several levels of nesting between user code and macro
-  code. For now this case has to be hygienized by hand.
-
-  Note 2: Converge has a pretty powerful approach of hygienic macros
-  in a Lisp-1 language; for long and boringly technical reasons, I
-  don't think its approch would be the best suited to metalua.
+  to a term rewriting subset of the language, which would be crippling
+  to use.
+
+  Note: inside hygiene, i.e. preventing macro code from capturing
+  variables in user code, is trivial to address through alpha
+  conversion, it's not the issue. The trickier part is outside
+  hygiene, when user's binders capture globals required by the
+  macro-generated code. That's the cause of pretty puzzling and hard
+  to find bugs. And the *really* tricky part, which is still an open
+  problem in metalua, is when you have several levels of nesting
+  between user code and macro code. For now this case has to be
+  hygienized by hand.
+
+  Note 2: Converge has a pretty powerful approach to hygienic macros
+  in a Lisp-1 language; for reasons that would be too long to expose
+  here, I don't think its approch would be the best suited to metalua.
+  But I might well be proved wrong eventually.
 
   Note 3: Redittors must have read that Paul Graham has released Arc,
   which is also a Lisp-1 with Common Lisp style macros; I expect this
@@ -260,49 +273,70 @@ Notworthy changes since 0.3
   hygiene, this will probably be the closest we can go to "macros for
   dummies" without creating an unmaintainable mess generator.
 
+  Besides, it's consistent with my official position that focusing on
+  superficial syntax issues is counter-productive most of the time :)
+
 
 - Lexers can be switched on the fly. This lets you change the set of
-  keywords temporarily, with the new gg.with_lexer() functor, or
-  handle radically different syntaxes in a single file (think
+  keywords temporarily, with the new gg.with_lexer() combinator. You
+  can also handle radically different syntaxes in a single file (think
   multiple-languages systems such as LuaTeX, or programs+goo as PHP).
 
 
-- Incorporation of the bugs listed on the mailing list and the blog.
+- Incorporation of the bug fixes reported to the mailing list and on
+  the blog.
 
 
 - New samples and extensions, in various states of completion:
 
-  - lists by comprehension, a la python/haskell. It includes lists
+  * lists by comprehension, a la python/haskell. It includes lists
     chunking, e.g. mylist[1 ... 3, 5 ... 7]
 
-  - anaphoric macros for 'if' and 'while' statements: with this
+  * anaphoric macros for 'if' and 'while' statements: with this
     extension, the condition of the 'if'/'while' is bound to variable
     'it' in the body; it lets you write things like:
-    while file:read '*l' do print(it) end.
+
+    > while file:read '*l' do print(it) end.
+
     No runtime overhead when 'it' isn't used in the body. An anaphoric
     variable should also be made accessible for functions, to let
     easily write anonymous recursive functions.
 
-  - continue statement, logging facility, ternary "?:" choice operator
-
-  - Try ... catch ... finally extension.
+  * Try ... catch ... finally extension. Syntax is less than ideal,
+    but the proper way to fix that is to refactor the match extension
+    to improve code reuse. There would be many other greate ways to
+    leverage a refactored match extension, e.g. destructuring binds or
+    multiple dispatch methods. To be done in the next version.
 
-  - with ... do extension: it uses try/finally to make sure that
+  * with ... do extension: it uses try/finally to make sure that
     resources will be properly closed. The only constraint on
-    resources is that they have to sport a :close() releasing method.
+    resources is that they have to support a :close() releasing method.
     For instance, he following code guarantees that file1 and file2
     will be closed, even if a return or an error occurs in the body.
 
-    with file1, file2 = io.open "f1.txt", io.open "f2.txt" do
-       contents = file1:read'*a' .. file2:read ;*a'
-    end
+    > with file1, file2 = io.open "f1.txt", io.open "f2.txt" do
+    >    contents = file1:read'*a' .. file2:read ;*a'
+    > end
+
+  * continue statement, logging facilities, ternary "?:" choice
+    operator, assignments as expressions, and a couple of similarly
+    tiny syntax sugar extensions.
+
+
+You might expect in next versions
+=================================
+The next versions of metalua will provide some of the following
+improvements, in no particular order: better error reporting,
+especially at runtime (there's a patch I've been too lazy to test
+yet), support for 64 bits CPUs, better support for macro hygiene, more
+samples and extensions, an adequate test suite, refactored libraries.
 
 
 Credits
 =======
 I'd like to thank the people who wrote the open source code which
 makes metalua run: the Lua team, the authors of Yueliang, Pluto, Lua
-Rings, Bitlib; the people whose bug reports, patches and insightful
-discussions dramatically improved the global design, including John
-Belmonte, Viacheslav Egorov, David Manura, Eric Raible, Laurence
-Tratt...
+Rings, Bitlib; and the people whose bug reports, patches and
+insightful discussions dramatically improved the global design,
+including John Belmonte, Viacheslav Egorov, David Manura, Olivier
+Gournet, Eric Raible, Laurence Tratt...
index 5a09386259286cdbe59e0b4eb4a73bc26308118c..a58417756b59dd1c53bad5a6a42a5f99db394be2 100755 (executable)
@@ -294,7 +294,7 @@ operator \verb+==+.
 
 \paragraph{Unary Operators}
 Unary operations are similar to binary operators, except that they
-only take the AST of one subexression.  The following table associates
+only take the AST of one subexression. The following table associates
 a Lua unary operator to its AST:
 
 \begin{center}
@@ -305,7 +305,7 @@ a Lua unary operator to its AST:
   \bf Op. & \bf AST \\
   
   \hline\hline %%%%%%%%%%%%%%
-  \verb+-+   & \verb+"sub"+ & 
+  \verb+-+   & \verb+"unm"+ & 
   \verb+#+   & \verb+"len"+ & 
   \verb+not+ & \verb+"not"+ \\
   \hline %%%%%%%%%%%%%%%%%%%%
@@ -314,11 +314,11 @@ a Lua unary operator to its AST:
 
 \subparagraph{Examples}
 \begin{itemize}
-\item \verb|-x| is represented as \verb|`Op{ `Sub, `Id "x" }|;
+\item \verb|-x| is represented as \verb|`Op{ 'unm', `Id "x" }|;
 \item \verb|-(1+2)| is represented as:\\
-  \verb|`Op{ `Sub, `Op{ `Add, `Number 1, `Number 2 } }|
+  \verb|`Op{ 'unm', `Op{ 'add', `Number 1, `Number 2 } }|
 \item \verb|#x| is represented as
-  \verb|`Op{ `Len, `Id "x" }|
+  \verb|`Op{ 'len', `Id "x" }|
 \end{itemize}
 
 \paragraph{Indexed access}
index 6d2cc049c08545d9f84d7f264e88247ae2a0d0a6..decec6d40c547b9bcbf70d7e26f986b9c7c03b95 100644 (file)
Binary files a/doc/manual/metalua-manual.pdf and b/doc/manual/metalua-manual.pdf differ
index d0b5c47b7b9f73b295203a4a11bc2c8856b6cd3a..98f3ca42340f2098fb3ce16dd0a7bed9964a5650 100644 (file)
@@ -1,4 +1,4 @@
-PLATFORMS = macosx mingw
+PLATFORMS = macosx mingw linux
 
 include config
 
index aeb32576bf26b320c73edb2d1a307acf02438d00..6c34e09a200f757d09166347290346c6d4550099 100644 (file)
@@ -18,5 +18,5 @@ clean:
 .PHONY: libraries install clean
 
 %.$(LIBEXT): %.$(OBJEXT)
-       $(MKLIB) -o $@ $+
+       $(MKLIB) -o $@ $+ $(LDFLAGS)
 
index ac8122bdab0537083315a7eb055ef1a2f2fcf92f..5e34d8cc69705b7c35e436e3bb0ada11f9d37b90 100644 (file)
@@ -46,6 +46,13 @@ ifeq ($(PLATFORM), mingw)
   LUA_BINARIES  = $(COMPILE).exe $(RUN).exe metalua.dll
 endif
 
+ifeq ($(PLATFORM), linux)
+  LIBEXT        = so
+  MKLIB         = gcc -shared
+  LDFLAGS      = -L../$(LUA_VM_DIR) -llua
+  LUA_BINARIES  = $(COMPILE) $(RUN)
+endif
+
 #########################################################
 # Environment variables settign paths
 
diff --git a/src/lib/autotable.lua b/src/lib/autotable.lua
deleted file mode 100644 (file)
index ede2ec2..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
---------------------------------------------------------------------------------
--- Tables that automatically generates subtables upon access.
---------------------------------------------------------------------------------
--- Borrowed from Lua-users, the Lua wiki.
--- (c) Thomas Wrensch & Rici Lake
---------------------------------------------------------------------------------
---
--- For instance, autotable().a.b.c = 42 is legal.
--- TODO: add proper pairs() and ipairs() iterators.
---------------------------------------------------------------------------------
-
-local meta, auto, assign
-
-function auto(tab, key)
-   return setmetatable({}, {
-      __index = auto,
-      __newindex = assign,
-      parent = tab,
-      key = key
-   })
-end
-
---------------------------------------------------------------------------------
--- The if statement below prevents the table from being created if the
--- value assigned is nil. This is, I think, technically correct but it
--- might be desirable to use assignment to nil to force a table into
--- existence.
---------------------------------------------------------------------------------
-function assign(tab, key, val)
-   -- if val ~= nil then
-   local oldmt = getmetatable(tab)
-   oldmt.parent[oldmt.key] = tab
-   setmetatable(tab, meta)
-   tab[key] = val
-   -- end
-end
-
-meta = {__index = auto}
-
-function autotable()
-   return setmetatable({}, meta)
-end
-
-
index 0546b992a3e76737ccee5c3fcf79c08d3d9611c6..4d2a10817e442d7ebc42b60b6e65183d8d771c24 100644 (file)
@@ -90,6 +90,8 @@ function H:__call (ast)
       -- free_vars is an old_name -> new_name dictionary computed from alpha:
       -- self.alpha is not an efficient representation for searching.
       if not alpha then alpha = { }; self.alpha = alpha end
+      -- FIXME: alpha should only be overridden when there actually are some
+      -- globals renamed.
       if #alpha==0 then alpha <- `Local{ { }, { } } end
       local new, old = unpack(alpha) 
       local free_vars  = { }
diff --git a/src/lib/extension/machine-runtime.mlua b/src/lib/extension/machine-runtime.mlua
deleted file mode 100644 (file)
index 41286d9..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-Machine = { }
-Machine.__index = Machine
-
---------------------------------------------------------------------------------
--- Default fields for new machine instances
---------------------------------------------------------------------------------
-Machine.template = { 
-   fenv          = { },
-   state         = 'init',
-   states        = { },
-   action_code   = { } }
-
---------------------------------------------------------------------------------
--- Events must be one of these. If not, cause a runtime error.
---------------------------------------------------------------------------------
-Machine.legal_events = table.transpose{ 'enter', 'update',  'exit' }
-
---------------------------------------------------------------------------------
--- Create a new machine isntance. [x] can be nil, or a table whose fields will
--- override the defaults provided by Machine.template.
---------------------------------------------------------------------------------
-function Machine:new(x)
-   local t = table.deep_copy (self.template)
-   if x then table.override(t, x) end
-   return setmetatable(t, self)
-end
-
---------------------------------------------------------------------------------
--- [process_msg] expects the machine [self] to be waiting for a message.
--- It gets such a message, does the appropriate state transition and
--- causes the appropriate event-triggered actions to be run.
--- Called by Machine:message() a.k.a. Machine:__call().
---------------------------------------------------------------------------------
-local function process_msg (self, msg)
-
-   -- Arg checking.
-   assert (type(msg)=='string', "Machine messages must be strings")
-   -- When there's a queue, new msgs are queued rather than executed directly.
-   self.msg_queue = { }
-
-   ---------------------------------------------------------
-   -- Determine the source and destination states.
-   ---------------------------------------------------------
-   local src_state = self.state
-   local dst_state = self.states[src_state].transitions[msg]
-   if not dst_state then 
-      error("Machine has no transition from state "..src_state..
-            " triggered by message "..msg)
-   end
-
-   ---------------------------------------------------------
-   -- Run the appropriate actions.
-   ---------------------------------------------------------
-   if src_state==dst_state then 
-      local update_actions = self.states[src_state].actions.update
-      for idx in ivalues(update_actions) do self.action_code[idx]() end
-   else
-      local exit_actions  = self.states[src_state].actions.exit
-      local enter_actions = self.states[dst_state].actions.enter
-      for idx in ivalues(exit_actions)   do self.action_code[idx]() end
-      for idx in ivalues(enter_actions)  do self.action_code[idx]() end
-   end
-   
-   ---------------------------------------------------------
-   -- Are there more messages queued? if so, process the next
-   -- one; if not, allow to process more messages directly
-   ---------------------------------------------------------
-   local next_msg = table.remove (self.msg_queue)
-   if next_msg then return process_msg (self, next_msg) -- tail call
-   else self.msg_queue = nil end -- ready for direct msg accept.
-end
-
---------------------------------------------------------------------------------
--- Send or queue a message to the machine, depending on whether it is already
--- processing a message.
--- Also registered as the machine's __call metamethod.
---------------------------------------------------------------------------------
-function Machine:message (msg)
-   if self.msg_queue then table.insert(self.msg_queue, msg)
-   else process_msg (self, msg) end
-end
-Machine.__call = Machine.message
-
---------------------------------------------------------------------------------
--- add a new code to execute whenever one of the events is triggered from one
--- of the states. Lists of events and states can be replaced by a raw string
--- when they would have been singletions: ":add_action({x}, {y}, z)" is the
--- same as ":add_action(x, y, z)". 
---------------------------------------------------------------------------------
-function Machine:add_action(states, events, code)
-   if type(states)~='table' then states={states} end
-   if type(events)~='table' then states={events} end
-   table.insert(self.action_code, code)
-   local action_idx = #self.action_code
-   for state in ivalues (states) do
-      for event in ivalues (events) do
-         if not self.legal_events[event] then 
-            error ("Illegal event "..table.tostring(event))
-         elseif not self.states[state] then
-            error ("No state "..table.tostring(state).." in this machine")
-         else
-            table.insert(self.states[state].actions, action_idx)
-         end
-      end
-   end
-end
-
---------------------------------------------------------------------------------
--- Add a new state. Causes a warning, but no error if the state already exists.
---------------------------------------------------------------------------------
-function Machine:add_state(state_name)
-   assert (type(state_name)=='string', "Machine states must be strings")
-   if self.states[state_name] then
-      printf ("*** Warning: state %q already exists in machine. ***", state_name)
-   else
-      self.states[state_name] = {
-         actions     = { enter = { }, update = { }, exit = { } },
-         transitions = { } } 
-   end
-end
-
---------------------------------------------------------------------------------
--- Add a new transition, from state src_state_name to dst_state_name, triggered
--- by msg. Cause a warning, but no error if there's already a transition from
--- this source state on this message, and override it.
---------------------------------------------------------------------------------
-function Machine:add_transition(src_state_name, msg, dst_state_name)
-   -- Check args and states existence.
-   assert (type(src_state_name)=='string', "Machine states must be strings")
-   assert (type(dst_state_name)=='string', "Machine states must be strings")
-   local src_state = self.states[src_state_name]
-   local dst_state = self.states[dst_state_name]
-   if not src_state then error("No state "..src_state.." in machine") end
-   if not dst_state then error("No state "..dst_state.." in machine") end
-
-   if src_state.transitions[msg] then      
-      printf ("*** Warning: overriding transition from state %s on msg %s. ***", 
-              src_state_name, msg)
-   end
-
-   src_state.transitions[msg] = dst_state_name
-end
-
-function Machine:restart()
-   self.state = 'init'
-   self.msg_queue = nil
-end
\ No newline at end of file
diff --git a/src/lib/extension/machine.mlua b/src/lib/extension/machine.mlua
deleted file mode 100644 (file)
index 0feb182..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
--{ extension 'match' }
-
-require 'strict'
-
---[===[ 
--- The following concrete syntax: --
-machine
-   state S1
-      when enter, update do foo() end
-      when enter do gnu() end
-      when exit do bar() end
-      on msg1 -> S1
-      on msg2 -> S2
-end
-
--- Will be translated into the following config: --
-{ states = { S1 = { name = "S1",
-                    actions = { enter  = { 1, 2 }, 
-                                update = { 1 },
-                                exit   = { 2 } }, 
-                    transitions = { msg1 = "S1",
-                                    msg2 = "S2" } } },
-  action_code = { [1] = function() foo() end,
-                  [2] = function() gnu() end } }
-                  [3] = function() bar() end } }
---]===]
-
-----------------------------------------------------------------------
--- Definitions:
--- * an _event_ is relative to a state. It can be:
---   + 'enter',  when we go in that state
---   + 'update', when we re-select the state we were already in.
---   + 'exit',   when we leave the state
--- * an _action_ is a function, associated with a state and an event.
--- * a _message_ is a token sent to the state machine, which determines
---   the next state that will be selected.
--- * an _entry_ is a line of data, attached to a string, as produced
---   by the parser. This builder's main purpose is to turn such
---   entries into a proper machine config.
-----------------------------------------------------------------------
-local function machine_builder (x)
-   
-   --print "Building machine"
-   local declared_states, used_states = { }, { }
-   local actions = { }
-   local last_action_idx = 0
-
-   ---------------------------------------------------------
-   -- First pass: gather the description of actions and
-   -- transitions, sorted by affected states, in
-   -- declared_states. state configs are indexed by name,
-   -- and have fields:
-   -- * name, their name;
-   -- * code, an event -> function id hashtable
-   -- * trans, a msg -> new state hashtable
-   --
-   -- Since actions can be bound to several events, they're
-   -- associated with a unique index that will be used
-   -- instead of the function itself, to prevent useless
-   -- duplication. All those names are collected in the
-   -- action_code hashtable, in the state's config.
-   --
-   -- This pass checks that there's no duplicate responses to 
-   -- messages or events.
-   ---------------------------------------------------------
-   for state in ivalues (x[1]) do
-      local state_id, state_entries = unpack(state)
-      local state_name = state_id[1]
-      --printf("  Building state %s, pass #1", state_name)
-      local state_cfg = declared_states[state_name]
-      if not state_cfg then
-         -- This state has no entry, create one.
-         state_cfg = { name        = state_name, 
-                       transitions = { },
-                       actions     = { enter  = `Table{ },
-                                       update = `Table{ }, 
-                                       exit   = `Table{ } } }
-         declared_states[state_name] = state_cfg
-      end
-
-      for entry in ivalues (state_entries) do
-         match entry with
-         -----------------------------------------
-         -- "when <id_list> do <block> end"
-         -----------------------------------------
-         | `When{ events, code } -> 
-            
-            -- Set action_idx->action_code in cfg.action_code
-            last_action_idx += 1
-            local action_idx = last_action_idx
-            actions [action_idx] = code
-            
-            -- Set ev_name->action_idx pairs in cfg[state].actions
-            for ev_id in ivalues (events) do
-               local ev_name = ev_id[1]
-               --printf("    Parsing event %s", ev_name)
-               local actions_list = state_cfg.actions[ev_name]
-               if not actions_list then
-                  error ("Invalid event "..ev_name.." in state "..state_name)
-               else
-                  table.insert(actions_list, `Number{action_idx})
-               end
-            end
-         -----------------------------------------
-         -- "on <msg_id> -> <state>"
-         -----------------------------------------
-         | `On{ messages, target_state } ->
-
-            -- Set msg_name->ttarget_name pairs in cfg[state].transitions
-            for msg_id in ivalues (messages) do
-               local msg_name, target_name = msg_id[1], target_state[1]
-               --printf("    Parsing transition %s -> %s", msg_name, target_name)
-               if state_cfg.actions[msg_name] then 
-                  error("Two transitions triggered by message "..msg_name..
-                        " in state "..state_name)
-               end
-               -- We'll later check that all target states exist.
-               used_states[target_name] = { msg=msg_name, src_state=state_name }
-               state_cfg.transitions[msg_name] = target_name
-            end -- for each msg
-         end -- match entry
-      end -- for each entry
-   end -- for each state
-
-   ---------------------------------------------------------
-   -- Check that every target state exists.
-   ---------------------------------------------------------
-   for a, b in pairs (used_states) do 
-      if not declared_states[a] then 
-         error ("State "..b.src_state.." tries to go to inexistant state "..a..
-                " when receiving message "..b.msg)
-      end
-   end
-
-   local states_ast = `Table{ }
-
-   ---------------------------------------------------------
-   -- 2nd pass: turn state configs into AST.
-   ---------------------------------------------------------
-   for state_cfg in values (declared_states) do
-      --printf("  Pass #2 for state %s", state_cfg.name)
-
-      -- Generate action name -> action code_idx hashtable.
-      local actions_entry = `Table{ }
-      for ev_name, action_indexes in pairs (state_cfg.actions) do
-         table.insert (actions_entry, 
-                       `Pair{ `String{ ev_name }, action_indexes })
-      end
-      -- Generate msg -> target state hastable.
-      local transitions_entry = `Table{ }
-      for msg_name, target_state in pairs (state_cfg.transitions) do
-         table.insert (transitions_entry, 
-                       `Pair{ `String{ msg_name }, `String{ target_state } })
-      end
-      -- Generate state config structure
-      local state_ast =
-         `Table{ `Pair{ `String 'actions',     actions_entry },
-                 `Pair{ `String 'transitions', transitions_entry } } 
-      -- Register state structure.
-      table.insert (states_ast, `Pair{ `String{ state_cfg.name }, state_ast })              
-   end
-
-   ---------------------------------------------------------
-   -- register the action name -> action code hashtable
-   ---------------------------------------------------------
-   local action_code_ast = `Table{ }
-   for action_idx, action_code in pairs (actions) do
-      table.insert (action_code_ast, `Pair{ `Number{ action_idx },
-                                            `Function{ { }, action_code } })
-   end
-
-   local cfg_ast = +{ { action_code = -{action_code_ast},
-                        states      = -{states_ast} } }
-
-   return +{stat: Machine:new(-{cfg_ast})}
-end
-
-local machine_entry = gg.multisequence{
-   { 'when', mlp.id_list, 'do', mlp.block, 'end', builder = 'When' },
-   { 'on', mlp.id_list, '->', mlp.id, builder = 'On' },
-   { 'do', mlp.block, 'end', builder =
-     |x| `When{ { `Id 'enter', `Id 'update' }, x[1] } } }
-
-local machine_state = gg.sequence{ 
-   'state', mlp.id, 
-   gg.list{ machine_entry, terminators = { 'state', 'end' } } }
-
-local machine_content = gg.sequence { name = 'State machine constructor',
-   gg.list{ machine_state, terminators = 'end' },
-   builder = machine_builder }
-
-mlp.lexer:add{ 'machine', 'state', 'when', 'on', '->' }
-mlp.expr:add{  'machine', machine_content, 'end', builder = |x|x[1] }
-mlp.stat:add{  'machine', mlp.expr, machine_content, 'end',
-   builder = |x| `Set{ {x[1]}, {x[2]} } }
-
-return +{ require 'extension.machine-runtime' }
\ No newline at end of file
index 6cb2b091f7e8acba507aa615e7fbb83412316f9d..0a7b5c4eba28252eee12fa72a77a84d963f425af 100644 (file)
@@ -99,7 +99,7 @@ function trycatch_builder(x)
 \r
    -- code handling the error catching process:\r
    local catch_result do\r
-      if #catch_cases>0 then\r
+      if catch_cases and #catch_cases>0 then\r
          ----------------------------------------------------------\r
          -- Protect catch code against failures: they run in a pcall(), and\r
          -- the result is kept in catch_* vars so that it can be used to\r
index 388768b2448e6cd5b233cd6f6a9f12abe41bf7dc..8007063802e9f3932eeb4679a467ff31e6176eea 100644 (file)
@@ -94,4 +94,4 @@ function extension (name, noruntime)
    end
 end
 
-return package
\ No newline at end of file
+return package
diff --git a/src/lib/srcdump.mlua b/src/lib/srcdump.mlua
deleted file mode 100644 (file)
index d2437b7..0000000
+++ /dev/null
@@ -1,266 +0,0 @@
-----------------------------------------------------------------------\r
--- Metalua samples:  $Id$\r
---\r
--- Summary: AST --> source code converter.\r
---\r
-----------------------------------------------------------------------\r
---\r
--- Copyright (c) 2006, Fabien Fleutot <metalua@gmail.com>.\r
---\r
--- This software is released under the MIT Licence, see licence.txt\r
--- for details.\r
---\r
---------------------------------------------------------------------------------\r
---\r
--- This sample takes an AST and converts it into a source string.\r
--- Once correctly polished, this will be a valuable tool to debug\r
--- hairy macros that generate hard to read AST.\r
---\r
---------------------------------------------------------------------------------\r
---\r
--- TODO:\r
--- - handle precedence correctly. Currently, expressions requiring parentheses\r
---   might or might not work.\r
---\r
---------------------------------------------------------------------------------\r
-\r
--- Runtime warning\r
-print [[Warning: you are using srcdump, an AST -> source converter, which is not correct yet wrt e.g. precedence and parentheses. Expect nasty bugs.]]\r
--- Compile-time warning\r
--{ print [[Warning: you are using srcdump, an AST -> source converter, which is not correct yet wrt e.g. precedence and parentheses. Expect nasty bugs.]] }\r
-\r
--{ extension 'match' }\r
-\r
-local opnames = {\r
- __add    = "+",    __sub    = "-",\r
- __mul    = "*",    __div    = "/",\r
- __mod    = "%",    __pow    = "^",\r
- __concat = "..",   __eq     = "==",\r
- __lt     = "<",    __le     = "<=",\r
- __and    = "and",  __or     = "or", \r
- __not    = "not ", __len    = "#" }\r
-\r
-local keywords = {\r
-    "and", "break", "do", "else", "elseif",\r
-    "end", "false", "for", "function", "if",\r
-    "in", "local", "nil", "not", "or", "repeat",\r
-    "return", "then", "true", "until", "while" }\r
-\r
-function dump (ast)\r
-   local indent_offset = 0\r
-   local accumulator = { }\r
-   local function indent() indent_offset += 1 end\r
-   local function dedent() indent_offset -= 1 end\r
-   local function acc(...) table.insert(accumulator, string.format(...)) end\r
-   local function newline() acc "\n"; acc (string.rep("   ", indent_offset)) end\r
-   local is_ident = |x| string.strmatch(x, "^[%a_][%w_]*$") and not keywords[x]\r
-\r
-   local parse_expr, parse_stat, parse_body, parse_funcdef, \r
-         parse_id, parse_list, parse_block\r
-\r
-   function parse_expr (ast)\r
-      match ast with\r
-      | `Nil       -> acc "nil"\r
-      | `Dots      -> acc "..."\r
-      | `True      -> acc "true"\r
-      | `False     -> acc "false"\r
-      | `Number{x} -> acc ("%i", x)\r
-      | `String{x} -> acc ("%q", x)\r
-      | `Id{ x }   -> parse_id (x)\r
-      | `Paren{ a }  -> acc "("; parse_expr (a); acc ")"\r
-\r
-      | `Op{ op, a, b } ->\r
-         -- FIXME: handle precedence and parentheses around [a] and [b]\r
-         parse_expr (a); acc (" %s ", opnames[op]); parse_expr (b)\r
-\r
-      | `Op{ op, a } ->\r
-         -- FIXME: handle precedence and parentheses around [a]\r
-         acc ("%s", opnames[op]); parse_expr (a)\r
-\r
-      | `Call{ f, `String{ _ } } | `Call{ f, `Table{ ... } } ->\r
-         -- FIXME: handle precedence and parentheses around [f]\r
-         parse_expr (f); acc " "; parse_expr (ast[2])\r
-\r
-      | `Call{ f, ... } ->\r
-         -- FIXME: handle precedence and parentheses around [f]\r
-         parse_expr (f)\r
-         acc " ("; parse_list (parse_expr, ast, ", ", 2); acc ")"\r
-\r
-      | `Method{ f, name, ... } ->\r
-         --CAVEAT: handle precedence and parentheses around [f]\r
-         parse_expr (f)\r
-         acc ":"; parse_id (name); acc " ("\r
-         parse_list (parse_expr, ast, ", ", 3)\r
-         acc ")"\r
-\r
-      | `Function{ params, body } ->\r
-         acc "function "; parse_funcdef (params, body)\r
-\r
-      | `Index{ t, `String{ k } } if is_ident(k) ->\r
-         --CAVEAT: handle precedence and parentheses around [t]\r
-         parse_expr (t); acc (".%s", k)\r
-\r
-      | `Index{ t,  k } ->\r
-         --CAVEAT: handle precedence and parentheses around [t]\r
-         parse_expr (t); acc "["; parse_expr (k); acc "]"\r
-       \r
-      | `Table{  } -> acc "{ }"\r
-\r
-      | `Table{ ... } ->\r
-         acc "{"\r
-         indent(); newline()\r
-         for i = 1, #ast do\r
-            match ast[i] with\r
-            | `Pair{ `String{ k }, v } if is_ident (k)-> \r
-               acc ("%s = ", k); parse_expr (v)\r
-            | `Pair{ k, v } -> \r
-               acc "["; parse_expr (k); acc "] = "; parse_expr (v)\r
-            | v -> \r
-               parse_expr (v)\r
-            end\r
-            if i < #ast then acc ";"; newline() end\r
-         end\r
-         acc " }"\r
-         dedent()\r
-\r
-      | `Stat{ b, e }  ->\r
-         acc "-{ `Stat{ +{ block:";\r
-         parse_block (b)\r
-         acc "}, +{ "\r
-         parse_expr (e)\r
-         acc " } } }"\r
-\r
-      | _ -> error ("Can't sourcedump expression " .. ast.tag)\r
-      end\r
-   end\r
-\r
-   function parse_funcdef (params, body)\r
-      acc " ("; parse_list (parse_expr, params, ", "); acc ")"\r
-      parse_block (body)\r
-      acc "end"\r
-   end\r
-\r
-   function parse_block (ast)\r
-      indent(); newline()\r
-      for i = 1, #ast do\r
-         parse_stat (ast[i])\r
-         if i == #ast then dedent() end\r
-         newline()\r
-      end\r
-   end\r
-\r
-   function parse_id (ast)\r
-      if type (ast) == "table" then ast = ast[1] end\r
-      assert (type(ast) == "string", "Invalid identifier")\r
-      if is_ident (ast) then acc ("%s", ast)\r
-      else acc ("-{`Id %q}", ast) end -- FIXME: might require parens in some cases\r
-   end\r
-\r
-   function parse_list (parser, list, sep, start, finish)\r
-      for i = start or 1, finish or #list do\r
-         parser (list[i])\r
-         if i<#list then acc ("%s", sep) end\r
-      end\r
-   end\r
-\r
-   function parse_stat (ast)\r
-      match ast with\r
-      | `Do{ ... } -> acc "do"; parse_block (ast); acc "end"\r
-\r
-      | `While{ cond, body } ->\r
-         acc "while "; parse_expr (cond); acc " do"\r
-         parse_block (body)\r
-         acc "end"\r
-\r
-      | `Repeat{ body, cond } ->\r
-         acc "repeat"\r
-         parse_block (body)\r
-         acc "until "; parse_expr (cond)\r
-\r
-      | `If{ ... } ->\r
-         for i = 1, #ast-1, 2 do\r
-            if i==1 then acc "if " else acc "elseif " end\r
-            parse_expr (ast[i])\r
-            acc " then"\r
-            parse_block (ast[i+1])\r
-         end\r
-         if #ast % 2 == 1 then\r
-            acc "else"\r
-            parse_block (ast[#ast])\r
-         end\r
-         acc "end"        \r
-\r
-      | `Fornum{ `Id{ var }, a, b, c, body } ->\r
-         acc "for "; parse_id (var); acc " = "\r
-         parse_expr (a); acc ", "\r
-         parse_expr (b); acc ", "\r
-         parse_expr (c); acc " do"\r
-         parse_block (body)\r
-         acc "end"\r
-\r
-      | `Fornum{ `Id{ var }, a, b, body } ->\r
-         acc "for "; parse_id (var); acc " = "\r
-         parse_expr (a); acc ", "\r
-         parse_expr (b); acc " do"\r
-         parse_block (body)\r
-         acc "end"\r
-\r
-      | `Forin{ varlist, vallist, body } ->\r
-         acc "for "; parse_list (parse_id, varlist, ", "); acc " = "\r
-         parse_list (parse_expr, vallist, ", ")\r
-         acc " do"\r
-         parse_block (body)\r
-         acc "end"\r
-\r
-      | `Local{ lhs, { } } ->\r
-         acc "local "\r
-         parse_list (parse_id, lhs, ", ")\r
-\r
-      | `Local{ lhs, rhs } ->\r
-         acc "local "\r
-         parse_list (parse_id, lhs, ", ")\r
-         acc " = "\r
-         parse_list (parse_expr, rhs, ", ")\r
-\r
-      | `Localrec{ { `Id{ name } }, { `Function{ params, body } } } ->\r
-         acc "local function "; parse_id (name); parse_funcdef (params, body)\r
-\r
-      | `Set{ { `Index{ obj, `String{ name } } }, \r
-              { `Function{ { `Id "self", ... }, body } } } ->\r
-         local params = ast[2][1][1]\r
-         acc "function "\r
-         parse_expr (obj); acc (":%s ", name); parse_funcdef (params, body)\r
-         \r
-      | `Set{ { lhs }, { `Function{ params, body } } } ->\r
-         acc "function "; parse_expr (lhs); parse_funcdef (params, body)\r
-\r
-      | `Set{ lhs, rhs } -> \r
-         parse_list (parse_expr, lhs, ", ")\r
-         acc " = "\r
-         parse_list (parse_expr, rhs, ", ")\r
-\r
-      | `Return{ ... } -> acc "return "; parse_list (parse_expr, ast, ", ")\r
-      | `Goto{ x } -> acc "-{ `Goto{ +{ "; parse_expr (x); acc " } } }" \r
-      | `Label{ x } -> acc "-{ `Label{ +{"; parse_expr (x); acc " } } }" \r
-\r
-      | { ... } if not ast.tag -> \r
-        for i = 1, #ast do\r
-           parse_stat (ast[i])\r
-           if i<#ast then newline() end\r
-        end\r
-     \r
-      | `Break         -> acc "break"\r
-      | `Call{ ... }   -> parse_expr (ast)\r
-      | `Invoke{ ... } -> parse_expr (ast)\r
-      | _              -> error ("Can't sourcedump statement " .. ast.tag)\r
-      end\r
-   end\r
-   \r
-   local expr_tags = { \r
-      Nil = 1, Dots = 1, True = 1, False = 1, Number = 1, String = 1, \r
-      Function = 1, Table = 1, Call = 1, Method = 1, Id = 1, Index = 1,\r
-      Op = 1 }\r
-\r
-   if expr_tags [ast.tag] then parse_expr (ast) else parse_stat (ast) end\r
-   return table.concat (accumulator)\r
-end
\ No newline at end of file
index 8be8338f36edf0f2208def1056947320cafe2c4f..f47ec0a805366608fd541e76b6e2bd2887379df3 100644 (file)
 ** (versions 3.2 and later) mark them as "hidden" to optimize access
 ** when Lua is compiled as a shared library.
 */
+#if 1 /* Metalua: export internal symbols needed by Pluto. */
+#  define LUAI_FUNC LUA_API
+#  define LUAI_DATA LUA_API
+#else /* Metalua: Original version, disabled */
 #if defined(luaall_c)
 #define LUAI_FUNC      static
 #define LUAI_DATA      /* empty */
 #define LUAI_FUNC      extern
 #define LUAI_DATA      extern
 #endif
+#endif
 
 
 
diff --git a/src/samples/fsm_test.mlua b/src/samples/fsm_test.mlua
deleted file mode 100644 (file)
index 1c5fb21..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
--{ extension 'machine' }
-
-machine M
-  state init
-    on MSG1, MSG2 -> S1
-  state S1
-    when enter do
-      print "do whatever you want in this Lua block" 
-      print "it will be evaluated every time the machine enters state S1"
-    end
-    on SOME_MSG -> S2 -- When the machine is in state S1 and receives msg
-                      -- SOME_MSG, jump to state S2.
-  state S2
-    do
-      print "there's no explicit 'when' before this action block" 
-      print "It's run when entering and updating the state by default"
-    end
-    on SOME_OTHER_MSG, OR_ANOTHER_MSG -> S1
- end
-
-table.print(M, 60)
\ No newline at end of file
index 127a95a33c9662468d6efb3b2fcacbfe524f04e4..87cd08a01664486e2954bd0c67f536b3d57d69b7 100644 (file)
@@ -3,10 +3,6 @@
 
 require 'metalua.compiler'
 
---assert (+{foo}.quote, "no q!?")
-
--- Usage samples:
-
 TEST_CASES = { 
 
    {  "everything should be renamed",
@@ -32,8 +28,6 @@ TEST_CASES = {
      +{ block:
         print(i)
         -{!`Call{`Id 'print', `String 'hi' } } 
-        -- Bugger. I don't detect any non-quoted element , so 
-        -- the -{+{ }} thingie won't protect from capture.
         -{!+{print 'hi'}} },
      { } },
  
@@ -49,10 +43,6 @@ TEST_CASES = {
         print (x, y) },
      {  alpha = +{stat: local RENAMED_PRINT = print}, 
         keep  = {y = true} } } } 
---   { +{ block: -- 
---         },
---     { } },
 
 for case in ivalues(TEST_CASES) do
    local comment, ast, cfg = unpack(case)
index 751794b53b278c8bf41aa52636a77edb3981c3e1..ca8346bbb0cf9828ecd12777bd0e3df970eacad1 100644 (file)
@@ -4,7 +4,7 @@
 
    require 'dollar'
 
-   local H = H:new{alpha={ }}
+   local H = H:new()
    print("initial H.alpha", H.alpha)
 
 
index b1a08c34f5051d3c2e5ef93097c1b1c9223633c4..3ac76d6cc9ea39c796746443499f481155eb058e 100644 (file)
@@ -135,3 +135,4 @@ local x = if false then 1 elseif bar then 2 else 3
 ------------------------------------------------------------
 
 assert (x == 3)
+print "It seems to work..."
\ No newline at end of file
index 3cfd955296fd6ace03633eafebb9d61ea231c52b..84b615c860342fce62ba171e6c664e77a215a036 100644 (file)
@@ -1,3 +1,8 @@
+-- This is a simple and somewhat stupid example of how to switch
+-- lexers dynamically. Behind a V, X and Y are the only reserved
+-- keywords. In normal conditions, X and Y aren't keywords and can be
+-- used as variables.
+
 -{ block:
    require 'lexer'
    local my_lexer = lexer.lexer:clone() -- no keywords
index ee0e2177d22b0e9eee8de5a46767aa00e8bb37d7..ec387d2e427ff27ff7828f7577db0df1228e4677 100644 (file)
@@ -13,8 +13,6 @@ ast = +{ block:
 disp = |msg,ast| printf("\n%s:\n%s", msg, table.tostring(ast, 80, 'nohash'))
 disp('initial term', ast)
 
-require'autotable'
-
 do -- Make globals explicit:
    local ast = table.deep_copy(ast)
    local cfg = { id = { } }
@@ -51,38 +49,3 @@ do -- Alpha rename local vars:
    disp('Local alpha-renamed', ast)
 end
 
-
---[=[
-
-
-local varlist_mt = { __index = function (self, key) 
-                                  local x={ }; self[key] = x; return x 
-                               end }
-local bound_vars = setmetatable({ }, varlist_mt)
-local free_vars  = setmetatable({ }, varlist_mt)
-
-cfg = { 
-   id = { 
-      bound = |x, binder| table.insert(bound_vars[binder], x),
-      free  = |x|         table.insert(free_vars[x[1]], x) } }
-
-walk_id.block(cfg, x)
-
--- Alpha convert bound variables
-for binder, occurences in pairs(bound_vars) do
-   local new_name = "_LOCAL_"..occurences[1][1]
-   local cfg = { binder = function (x) x[1]=new_name; return 'break' end }
-   walk.guess(cfg, binder)
-   for occ in ivalues(occurences) do occ[1] = new_name end
-end
-
--- Alpha convert free variables
-for name, occurences in pairs(free_vars) do
-   local new_name = "_GLOBAL_"..occurences[1][1]
-   for occ in ivalues(occurences) do occ[1] = new_name end
-end   
---]=]
-
---print "\n\n TERM AFTER PARSING:"
---table.print(x,60,'nohash')
-
index a0b92dd3117716314e10bc979355c774d5dac14b..76af4469d37e9f0a3eb12df71ffa622c0ba81dc5 100644 (file)
@@ -1,5 +1,5 @@
-set MLUALIB_TARGET=d:\fft\tmp\mlualib\r
-set MSVCDIR=c:\devtools\msvc\vc98\bin\r
+set MLUALIB_TARGET=c:\tmp\mlualib\r
+set MSVCDIR=c:\msvc\vc98\bin\r
 md %MLUALIB_TARGET%\r
 \r
 :lua\r
@@ -7,9 +7,8 @@ md %MLUALIB_TARGET%
 @REM Code taken straight from Lua's etc/luavs.bat\r
 cd lua\r
 %MSVCDIR%\cl /nologo /MD /O2 /W3 /c /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /DLUA_BUILD_AS_DLL l*.c\r
-%MSVCDIR%\cl /nologo /MD /O2 /W3 /c /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /DLUA_BUILD_AS_DLL /DLUA_CORE /I . ../binlibs/pluto.c\r
 del lua.obj luac.obj\r
-%MSVCDIR%\link /nologo /DLL /out:lua51.dll l*.obj pluto.obj\r
+%MSVCDIR%\link /nologo /DLL /out:lua51.dll l*.obj\r
 %MSVCDIR%\cl /nologo /MD /O2 /W3 /c /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /DLUA_BUILD_AS_DLL lua.c\r
 %MSVCDIR%\link /nologo /out:lua.exe lua.obj lua51.lib\r
 %MSVCDIR%\cl /nologo /MD /O2 /W3 /c /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE l*.c print.c\r
@@ -30,20 +29,15 @@ xcopy /E /Y lib %MLUALIB_TARGET%
 cd binlibs\r
 %MSVCDIR%\cl /nologo /LD /DLUA_BUILD_AS_DLL /DLUA_LIB /DBUILTIN_CAST /I..\lua bit.c ..\lua\lua51.lib\r
 %MSVCDIR%\cl /nologo /LD /DLUA_BUILD_AS_DLL /DLUA_LIB /I..\lua rings.c ..\lua\lua51.lib\r
+%MSVCDIR%\cl /nologo /LD /DLUA_BUILD_AS_DLL /DLUA_LIB /I..\lua pluto.c ..\lua\lua51.lib\r
 xcopy /Y rings.dll %MLUALIB_TARGET%\r
-xcopy /Y bit.dll %MLUALIB_TARGET%\r
+xcopy /Y bit.dll   %MLUALIB_TARGET%\r
+xcopy /Y pluto.dll %MLUALIB_TARGET%\r
 cd ..\r
 \r
 :w32stub\r
-@REM Pluto has been compiled into lua, for DLL exportation reasons. Provide a stub\r
-cd win32\r
-%MSVCDIR%\cl /nologo /c /DLUA_BUILD_AS_DLL /I..\lua pluto_w32_stub.c\r
-%MSVCDIR%\link /nologo /DLL /out:pluto_w32_stub.dll pluto_w32_stub.obj ..\lua\lua51.lib\r
-xcopy /Y  pluto_w32_stub.dll %MLUALIB_TARGET%\r
-xcopy /Y  pluto.lua %MLUALIB_TARGET%\r
 echo @set LUA_ROOT=%MLUALIB_TARGET%> %MLUALIB_TARGET%\metalua.bat\r
-type metalua.bat >> %MLUALIB_TARGET%\metalua.bat\r
-cd ..\r
+type win32\metalua.bat >> %MLUALIB_TARGET%\metalua.bat\r
 \r
 :setenv\r
 @REM set Metalua environment\r
@@ -51,7 +45,7 @@ echo set LUA_ROOT=%MLUALIB_TARGET% > mlua_setenv.bat
 echo set LUA_PATH=?.luac;?.lua;%MLUALIB_TARGET%\?.luac;%MLUALIB_TARGET%\?.lua >> mlua_setenv.bat\r
 echo set LUA_CPATH=?.dll;%MLUALIB_TARGET%\?.dll;%MLUALIB_TARGET%\?\linit.dll >> mlua_setenv.bat\r
 echo set LUA_MPATH=?.mlua;%MLUALIB_TARGET%\?.mlua >> mlua_setenv.bat\r
-REM echo set PATH=%MLUALIB_TARGET%;%PATH% >> mlua_setenv.bat\r
+echo set PATH=%MLUALIB_TARGET%;%PATH% >> mlua_setenv.bat\r
 CALL mlua_setenv.bat\r
 \r
 :compiler\r