I try to summarize all my feedback after this work.
I hope give you some subjects for next parrot sketches.


I) ISSUES

1) Closure & lexical scoping rules
This is the biggest issue versus Lua specifications.
The TODO test in languages/lua/t/closure.t (line 73) shows it
(see also http://www.lua.org/manual/5.1/manual.html#2.6).
I think that Lua needs some think like a specific DynLexPad,
but I can't do this task (too complex for me).


2) Metamethod __call
2 TODO tests in languages/lua/t/metatable.t (line 506 & 539) show this issue.
In languages/lua/pmc/luaany.pmc (line 250), the invoke method must manipulate
arguments because with the following PIR example :
        result = obj(arg1, arg2)
the metamethod __call retrieved in the metatable of obj, must be call with
3 parameters (obj, arg1, arg2).


3) garbage collection
How write code without GC problems ?
How track down and fix GC problems ?


4) library debug
This library deals with some low level of the Lua VM (see
http://www.lua.org/manual/5.1/manual.html#5.9).
What's possible with Parrot VM ?


5) back trace & friends
Currently, back trace speaks PIR, and it's fine for debugging.
But in future, it must speak Lua (source name & line number).



II) SUGGESTIONS & QUESTIONS

Concerns the scope of Parrot core, platform assumption (POSIX ?)

1) os.time needs mktime
My current implementation uses a NCI method in lua.pmc (line 206).
Another implementation could be an opcode mktime (the reverse of
decodelocaltime, with the same array definition)
There are the following opcodes : time, gmtime, localtime, decodetime
& decodelocaltime.
It seems that Parrot follows Perl5 where gmtime, localtime, time, times are
builtins functions and mktime is supplied by POSIX::mktime.
If someone has a better explanation or the real reason, I'm interested.

2) os.tmpname
My current implementation uses a NCI method in lua.pmc (line 312)
that calls a C POSIX function (platform dependant: tmpnam or mkstemp).
Another implementation could be a method in the PMC random or ParrotIO.

3) os.tmpfile
My current implementation uses a ParrotIO (so, a standard file) and
the POSIX behavior of unlink for the final destroy.
So, this implementation depends of the platform (really POSIX or not).
Another implementation could be ParrotIO-tmp : a subclass of ParrotIO
with a constructor without filename and a finalizer responsible of the
destroy of the file.
Another implementation could be ParrotIO-String (like the Perl module
IO::String) where temporary files live only in memory.

4) io.popen
pipe in ParrotIO not fully implemented.

5) file:setvbuf
My implementation depends on the methods buffer_type & buffer_size of
ParrotIO PMC.
Currently, these 2 methods are only specified, but not implemented.

6) lfs.touch (utime)
Not yet implemented.
utime could be a method of OS PMC (not found in any documentation).

7) lfs.lock & lfs.unlock
Same as lfs.touch.


III) CRAZY BUGS

1) command line arguments lost in the call tree
        $ cat arg.lua
        print(...)
        print(debug.traceback())
        $ parrot luap.pir --target=pir arg.lua > arg.pir
        $ parrot --no-gc arg.pir arg1 arg2
# correct
        arg1    arg2
        stack traceback:
                arg.pir:41 in function '&main_10'
                languages/lua/lib/luaaux.pir:601 in function 'docall'
                arg.pir:17 in function '&start'

        $ parrot --no-gc lua.pbc arg.lua arg1 arg2
# BAD: all arguments are lost

        stack traceback:
                EVAL_1:41 in function '&main_10'
                languages/lua/lib/luaaux.pir:601 in function 'docall'
                lua.pir:302 in function 'handle_script'
                lua.pir:122 in function 'main'

When I add some trace code, I see the correct value in 'docall' just before
line 601and after it's the same generated code.


2) other argument lost
On Lua, the mecanism of package uses 2 functions : require & module.
        $ cat mod.lua
        print("modname:", ...)  -- must print "mod" when called by require
        print(debug.traceback())
        $ parrot --no-gc lua.pbc -e "require 'mod'"
        modname:
        stack traceback:
                EVAL_2:43 in function '&main_34'
                languages/lua/lib/luapackage.pir:463 in function 'require'
                EVAL_1:33 in function '&main_10'
                languages/lua/lib/luaaux.pir:601 in function 'docall'
                lua.pir:352 in function 'dostring'
                lua.pir:246 in function 'runargs'
                lua.pir:119 in function 'main'

now, if you duplicate the line 463 in luapackage.pir [ $P0 = $P1(modname) ],
the second call is correct.

        $ parrot --no-gc lua.pbc -e "require 'mod'"
        modname:
        stack traceback:
                EVAL_2:43 in function '&main_34'
                languages/lua/lib/luapackage.pir:463 in function 'require'
                EVAL_1:33 in function '&main_10'
                languages/lua/lib/luaaux.pir:601 in function 'docall'
                lua.pir:352 in function 'dostring'
                lua.pir:246 in function 'runargs'
                lua.pir:119 in function 'main'

        modname:        mod
        stack traceback:
                EVAL_2:43 in function '&main_34'
                languages/lua/lib/luapackage.pir:464 in function 'require'
                EVAL_1:33 in function '&main_10'
                languages/lua/lib/luaaux.pir:601 in function 'docall'
                lua.pir:352 in function 'dostring'
                lua.pir:246 in function 'runargs'
                lua.pir:119 in function 'main'



IV) OTHERS REMARKS

1) Compiler Tools
The size of Lua compiler (without PMC and runtime libraries) is 3 KLOC.
It's a result of the quality of the common tools HLLCompiler, PAST-pm, PGE, TGE
Now, I'm waiting for PCT, the next generation.


2) a Memoize module for compiler
Many languages use regex, but few store regex in variable,
so all others need a Memoize mecanism (well-known optimization) that store
the result of the compilation.


3) learning curve
It's not easy to learn all things needed by language implementation in Parrot.
There are a lot of knowledges :
        - Parrot infrastructure (configuration tools, test environment)
        - PIR
        - PMC
        - PGE, TGE, ...
So, in a first step, I write a compiler with Perl & yapp that generates
PIR, after I add a Lua runtime library, and finally I write in PIR (with PGE/TGE)
a compiler.


That's all for this time.

François.



Reply via email to