micropython

Annotated docs/evaluation.txt

438:b547786f38c7
2011-07-02 Paul Boddie Moved some code generation methods into a new Assembler class. Separated sequence element storage into a separate method which may form the basis of a native library routine.
paul@153 1
Instruction Evaluation Model
paul@153 2
============================
paul@153 3
paul@153 4
Programs use a value stack containing local and temporary storage. A value
paul@153 5
stack pointer indicates the top of this stack. In addition, a separate stack
paul@153 6
is used to record the invocation frames. All stack pointers refer to the next
paul@153 7
address to be used by the stack, not the address of the uppermost element.
paul@153 8
paul@153 9
    Frame Stack     Value Stack
paul@153 10
    -----------     -----------     Address of Callable
paul@153 11
                                    -------------------
paul@153 12
    previous        ...
paul@153 13
    current ------> callable -----> identifier
paul@153 14
                    arg1            reference to code
paul@153 15
                    arg2
paul@153 16
                    arg3
paul@153 17
                    local4
paul@153 18
                    local5
paul@153 19
                    ...
paul@153 20
paul@153 21
Unlike the CPython virtual machine, programs do not use a value stack
paul@153 22
containing the results of expression evaluations. Instead, temporary storage
paul@153 23
is statically allocated and employed by instructions.
paul@153 24
paul@153 25
Loading local names and temporary values is a matter of performing
paul@153 26
frame-relative accesses to the value stack.
paul@153 27
paul@153 28
Invocations and Argument Evaluation
paul@153 29
-----------------------------------
paul@153 30
paul@153 31
When preparing for an invocation, the caller first sets the invocation frame
paul@153 32
pointer. A number of locations for the arguments required by the invocation
paul@153 33
are then reserved. With a frame to prepare, positional arguments are added to
paul@153 34
the frame in order such that the first argument positions are filled. The
paul@153 35
names of keyword arguments are used (in the form of table index values) to
paul@153 36
consult the parameter table and to find the frame location in which such
paul@153 37
arguments are to be stored.
paul@153 38
paul@153 39
    fn(a, b, d=1, e=2, c=3) -> fn(a, b, c, d, e)
paul@153 40
paul@153 41
    Frame
paul@153 42
    -----
paul@153 43
paul@153 44
    a               a               a               a
paul@153 45
    b               b               b               b
paul@153 46
    ___             ___             ___         --> 3
paul@153 47
    ___         --> 1               1           |   1
paul@153 48
    ___         |   ___         --> 2           |   2
paul@201 49
                |               |               |
paul@153 50
    1 -----------   2 -----------   3 -----------
paul@153 51
paul@153 52
Conceptually, the frame can be considered as a collection of attributes, as
paul@153 53
seen in other kinds of structures:
paul@153 54
paul@153 55
Frame for invocation of fn:
paul@153 56
paul@153 57
    0           1           2           3           4           5
paul@153 58
    code        a           b           c           d           e
paul@153 59
    reference
paul@153 60
paul@153 61
However, where arguments are specified positionally, such "attributes" are not
paul@153 62
set using a comparable approach to that employed with other structures.
paul@153 63
Keyword arguments are set using an attribute-like mechanism, though, where the
paul@153 64
position of each argument discovered using the parameter table.
paul@153 65
paul@153 66
Method Invocations
paul@153 67
------------------
paul@153 68
paul@153 69
Method invocations incorporate an implicit first argument which is obtained
paul@153 70
from the context of the method:
paul@153 71
paul@153 72
    method(a, b, d=1, e=2, c=3) -> method(self, a, b, c, d, e)
paul@153 73
paul@153 74
    Frame
paul@153 75
    -----
paul@153 76
paul@153 77
    context of method
paul@153 78
    a
paul@153 79
    b
paul@153 80
    3
paul@153 81
    1
paul@153 82
    2
paul@153 83
paul@153 84
Although it could be possible to permit any object to be provided as the first
paul@153 85
argument, in order to optimise instance attribute access in methods, we should
paul@153 86
seek to restrict the object type.
paul@153 87
paul@153 88
Verifying Supplied Arguments
paul@153 89
----------------------------
paul@153 90
paul@153 91
In order to ensure a correct invocation, it is also necessary to check the
paul@153 92
number of supplied arguments. If the target of the invocation is known at
paul@153 93
compile-time, no additional instructions need to be emitted; otherwise, the
paul@153 94
generated code must test for the following situations:
paul@153 95
paul@153 96
 1. That the number of supplied arguments is equal to the number of expected
paul@153 97
    parameters.
paul@153 98
paul@153 99
 2. That no keyword argument overwrites an existing positional parameter.
paul@153 100
paul@153 101
Default Arguments
paul@153 102
-----------------
paul@153 103
paul@153 104
Some arguments may have default values which are used if no value is provided
paul@153 105
in an invocation. Such defaults are initialised when the function itself is
paul@153 106
initialised, and are used to fill in any invocation frames that are known at
paul@153 107
compile-time.
paul@153 108
paul@153 109
Tuples, Frames and Allocation
paul@153 110
-----------------------------
paul@153 111
paul@153 112
Using the approach where arguments are treated like attributes in some kind of
paul@153 113
structure, we could choose to allocate frames in places other than a stack.
paul@153 114
This would produce something somewhat similar to a plain tuple object.