diff options
| author | Drahflow <drahflow@gmx.de> | 2014-03-31 00:24:05 +0200 |
|---|---|---|
| committer | Drahflow <drahflow@gmx.de> | 2014-03-31 00:24:05 +0200 |
| commit | c61d0d4fe1079dfe5e1b40e0f301d6d1c77a136d (patch) | |
| tree | 0593f2091ec513b863728088db66a10859f73735 /doc/scopes.md | |
| parent | 2387a3eafbd13c0b27797ac1434e45bb36d632c2 (diff) | |
Some documentation (and resulting code-cleanup)
Diffstat (limited to 'doc/scopes.md')
| -rw-r--r-- | doc/scopes.md | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/doc/scopes.md b/doc/scopes.md new file mode 100644 index 0000000..1bed056 --- /dev/null +++ b/doc/scopes.md @@ -0,0 +1,108 @@ +Scopes +====== + +A scope maps (variable) names to values. Each such binding also specifies how and when the referenced +object gets executed and what assumptions the optimizer may make about later values of the same name. +To create a mapping from a name to a value, various functions starting with `def` exist. Some of them +are aliased to `==` and similar functions. + +They allow specifying four different execution modes: +* _v_alue: Upon dereference, the object is placed on top of the stack. +* _f_unction: Upon dereference, the object is executed (equivalently the object is placed on top of the stack, then `*` is executed). +* _m_ember: Upon dereference, the containing scope is pushed on the stack, then the object is executed. +* _q_uoting: The object is executed as soon as the name is encountered in the input stream, even if the parser is currently in quote + mode. + +They also allow specifying four different optimization guarantees: +* _s_tatic: The name always resides at the same scope slot. Scope slots are assigned deterministically. If the same set of variables + is always declared in scopes encountered by a certain piece of code, then this piece of code can savely assume static + names. This also guarantees that the execution mode of this name is always the same. +* _t_ype constant: The name always refers to the same type of object. If the variable held an integer once, it is required + to always hold an integer and so on. Arrays and functions are only type constant if they keep the same + function signature (i.e. same nesting depth in case of arrays). +* _c_onstant: The referenced object stays identical forever. This implies static and type constant. +* _d_eep constant: The referenced object and all objects reached through it (i.e. submembers in case of a scope) stay identical forever. + This implies constant. + +No optimization guarantees can be specified for quoting execution mode, as optimization is not applied in this parsing stage. + +The resulting function names are the concatenation of `def`, the desired execution mode character (`v`, `f`, `m`, `q`) and the +desired optimization guarantee (none, `s`, `t`, `st`, `c`, `d`). + +This scheme results in 19 different functions. All of these functions take from the stack a name (on top of stack) and a value +to associate with the name. + + 5 /five defv + { "hi" dump } /greet deffst + 42 "ANSWER" defvd + +Some of these functions are aliased, because they appear particularly useful: + +* `==?` aliases `defv`, i.e. value definition without optimization guarantees +* `==` aliases `defvst`, i.e. value definition with static and type constness +* `==:` aliases `defvd`, i.e. value definition with deep constness +* `=*?` aliases `defv`, i.e. executable definition without optimization guarantees +* `=*` aliases `defvst`, i.e. executable definition with static and type constness +* `=*:` aliases `defvd`, i.e. executable definition with deep constness + +The value associated with a name can be updated using the `=` function. It takes a name to update and the new value from the stack. + + 0 ==i + i 1 add =i + i dump + 0000000000000001 + + +Scope objects on the stack +-------------------------- + +There is always a current scope. This is the scope where lookup happens during code parsing and this is where the `def` function +family puts values. The current scope object can also be put on the stack using the `scope` function. All scope objects but the +global one have a single parent scope where lookup continues if a name can not be resolved in the scope itself. + +The current scope can also be switched using `<` and `>`. `<` takes the current scope as the parent of a new scope which then +becomes current. `>` pushes the current scope to the stack and makes its parent the new current scope. This allows construction +of structured datatypes. To this end, the `.` function takes a name and a scope object from the stack and resolves the name in +the given scope object. + + < + 1 ==one + > _ dump + <scope: 00006000005DDAA0> + .one dump + 0000000000000001 + +Function objects created by a `{`, `}` pair remember the scope they have been created in. Upon execution, they create a new +scope object which has this remembered scope as its parent. In effect, this results in closure semantics for function objects. + + < + 0 ==i + { i dump i 1 add =i } + > -- /dumpAndIncrement deffst + dumpAndIncrement + 0000000000000000 + dumpAndIncrement + 0000000000000001 + dumpAndIncrement + 0000000000000002 + +Sometimes it's useful to assign a different parent pointer than the current scope to a new scope object. This can be +achieved by the `>'` function. It behaves like `>` but takes the parent pointer of the new object from the stack. + + < + 0 ==i + > ==parent + < + { i dump i 1 add =i } + parent + >' -- /dumpAndIncrement deffst + dumpAndIncrement + 0000000000000000 + dumpAndIncrement + 0000000000000001 + dumpAndIncrement + 0000000000000002 + +As `>'` only assigns the parent pointer when the scope stops being the current scope, before its execution the parent +was set as usual, i.e. the current scope before `<`. This allows for interesting possibilities. Note that names in +quoted mode are only resolved during first execution. |
