First you'll have to understand, that Perl program execution is a mixture of parsing, interpretation and compilation :
Quote
The perl executable you are using has two distinct stages. First comes the frontend, which is certainly a compiler of sorts. It compiles your perl program source into a parse tree. This compiler then performs various optimizations such as one would find in any other compiler, including throwing out unreachable code, reducing constant expressions to their results, and loading in certain library definitions. It is at this point that the use statements get run, since they are semantically equivalent to BEGIN{} blocks wrapping a require and an import() class-method call against the included module. End of compilation.
Next comes the backend, which is certainly an interpreter of sorts; let's call it a PP interpreter for now, just because. While what it actually executes is a parse tree and not byte code per se, still we would not go wrong in classifying this backend as a byte-code interpreter (like java or python). This is useful in particular when it comes to distinguishing these languages from ``pure'' interpreters, such as most shell and tcl implementations you happen to run. This is where any requires not wrapped in BEGINs occur.. . .br>
From the frontend (the ``source-code to parse-tree'' compiler), you can get at the backend (the PP interpreter) via a BEGIN subroutine. Likewise, to go the other way (get back to the compiler from the interpreter), you can use an eval("string") or a s/foo/bar/ee notation. By the way, despite appearances to the contrary, it turns out that an eval { BLOCK } and s/foo/bar/e are not actually hooks back to the compiler; it already handled them long ago and far away.)
Put another way
Quote
When the Perl compiler is fed a Perl program, the first task it performs is lexical analysis: breaking down the program into its basic syntactic elements (often called tokens). If the program is:
print "Hello, world!\n";
the lexical analyzer breaks it down into three tokens: print, "Hello, world!\n", and the final semicolon. The token sequence is then parsed, fixing the relationship between the tokens. In Perl, the boundary between lexical analysis and parsing is blurred more than in other languages. (Other computer languages, that is. . . .
Once a program has been parsed . . ., it is compiled into a tree of opcodes representing low-level operations, and finally that tree of operations is executed--unless you invoked Perl with the -c ("check syntax") switch, which exits upon completing the compilation phase. . . . As the tree of opcodes constituting a compiled Perl program is executed, Perl values are created, manipulated, and destroyed.
For details, see:
Programming Perl: Internals and Externals
Perl in a nutshell: The Perl Interpreter
Introduction to the Perl Compiler-Translator
quote:
Perl has always had a compiler: your source is compiled into an internal form (a parse tree) which is then optimized before being run. Since version 5.005, Perl has shipped with a module capable of inspecting the optimized parse tree (B), and this has been used to write many useful utilities, including a module that lets you turn your Perl into C source code that can be compiled into an native executable.
The B module provides access to the parse tree, and other modules (``back ends'') do things with the tree. Some write it out as bytecode, C source code, or a semi-human-readable text. Another traverses the parse tree to build a cross-reference of which subroutines, formats, and variables are used where. Another checks your code for dubious constructs. Yet another back end dumps the parse tree back out as Perl source, acting as a source code beautifier or deobfuscator.
Because its original purpose was to be a way to produce C code corresponding to a Perl program, and in turn a native executable, the B module and its associated back ends are known as ``the compiler'', even though they don't really compile anything. Different parts of the compiler are more accurately a ``translator'', or an ``inspector'', but people want Perl to have a ``compiler option'' not an ``inspector gadget''. What can you do?
Best regards,
Allan Dystrup
| [reply] [d/l] |
Back to my question, as I understand, perl code also need to be compiled and excuted(like C).
That's not exactly how it works. The way perlcc worked was to write a C program that contained the Perl interpreter as well as the source code in a serialized format. The program launched the Perl interpreter, then fed it the source code. If you think about what it takes to run Perl, you'll realize that you need the whole interpreter around in case you have an eval STRING construct of some kind. There's no direct translation of Perl statements to assembly language, which I think is what you wanted.
The whole point is moot though because perlcc never worked very well and no one wants to maintain it.
| [reply] [d/l] |
xiaoyafeng:
You might want to try the B::Terse and similar modules. They will show you the bytecode generated by the perl compiler. It's not exactly assembler, but can be very useful in learning some of the fundamentals of the system, much like the native assembly language is very useful in understanding many concepts.
Trivial example:
$ perl -MO=Terse -e 'print "foo!\n"'
LISTOP (0x10122248) leave [1]
OP (0x10033b50) enter
COP (0x100253d8) nextstate
LISTOP (0x10122220) print
OP (0x1002fcf0) pushmark
SVOP (0x100252e0) const [2] PV (0x10010f90) "foo!\n"
-e syntax OK
...roboticus
| [reply] [d/l] |
Terse was replaced with Concise (and now Terse is just a wrapper that calls Concise).
Concise, by default shows a bit more info:
$ perl -MO=Concise -e 'print "foo!\n"'
6 <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 1 -e:1) v ->3
5 <@> print vK ->6
3 <0> pushmark s ->4
4 <$> const[PV "foo!\n"] s ->5
-e syntax OK
Or in execution order, instead of the syntax tree:
$ perl -MO=Concise,-exec -e 'print "foo!\n"'
1 <0> enter
2 <;> nextstate(main 1 -e:1) v
3 <0> pushmark s
4 <$> const[PV "foo!\n"] s
5 <@> print vK
6 <@> leave[1 ref] vKP/REFC
-e syntax OK
See B::Concise for what all that densely packed info means. | [reply] [d/l] [select] |
| [reply] |
An example may help. Ook! is a small language which makes it fairly easy to write an interpreter for it. For a sample see my attempt at a Perl Ook interpreter. Note that there is no translation to assembly language. A minor translation to an internal representation of the language tokens makes the implementation cleaner, but doesn't generate anything that is new or different than the Ook! source code.
So, how does it work? It works by creating a mini-computer in software (a virtual machine) and runs the code in that environment - no assembly required (or even batteries).
Perl is environmentally friendly - it saves trees
| [reply] |
| [reply] |