StackTalkDesign.txt
· 4.6 KiB · Text
Ham
Playground
title[ StackTalk ]
"Stack Basics" note[
An object is a collection of named stacks
A quotation is a malleable list of code symbols, delimited by [ and ]
Strings can be written two ways:
"This is a conventional string"
this-is-a-symbol-string:
There are 4 baseline stack operations:
`$value $stack push`
`$stack pop`
`$stack peek`
`$stack run`
These let you manipulate arbitrarily named stacks.
`run` is a bit special. It'll run top of $stack, if it is a
quotation, otherwise it acts like peek
There are shortcuts for these operations:
[ 1 x: push ] can be writtn as [ 1 >x ]
[ x: peek ] can be written as [ x. ] when you need no ambiguity
[ x: pop ] can be written as [ x> ]
[ x: run ] can be written as [ x ]
]
"Quotation suffix autoswap" note[
This one is a little inspired by https://knucklecracker.com/wiki/doku.php?id=crpl:overview#warp_notation,
but is ultimately a bit less generalized.
I anticipate that quotations will be modified by a lot of words. Because of this, and because
I think it reads better in a lot of cases, there's another rewrite
[ 1 [ me> 1 + >me ] do ] can be written as [ 1 do[ me> 1 + >me ] ]
This is how `note` has been working.
This doesn't generalize to arbitrary word movement, just for quotations.
]
Objects: note[
The current Object/scope is the top of the `me:` stack.
`do` executes the quotation inside the scope of object below
it in the stack.
`$subject $quotation do`
do single command Shorthand:
[ AnObject [ aThing ] do ] can be written as [ AnObject .aThing ]
You can use an existing object as a starting point for one of your own via `clone`
[ 0 0 Object clone do[ >y >x ] >my2dPoint ]
]
Quotations: note[
Quotations are a swiss-army-knife of a code structure
You can call `string` on them to get their contents.
[ [ a thing ] .string NB[ stack is " a thing " ] ]
`interpolate` will copy values from the containing scope based on $names
[ 1 >a 2 >b interpolate[ $a $b + ] NB[ stack is [ 1 2 + ] ]
Objects copied this way are copied by reference, rather than deep cloned.
You can get the list of symbols from a quotation
code[
[ @ @ -- @ ] symbols each[ println ]
NB[ print output:
"@"
"@"
"--"
"@"
]
]
You can supply an interpretation ruleset, on the left side, you have patterns, on the right, consequent actions
The patterns match against one or more symbols (as fetched by `symbols`).
[ @ @ -- @ ] obj[ 0 >numInputValues 0 >numOutputValues input: >mode ]
interperet[
@ [ input: mode ] -> [ numInputValues: inc ]
-- [ input: mode ] -> [ output: >mode ]
@ [ output: mode ] -> [ numOutputValues: inc ]
* -> [ [ "Unrecogized symbol" _ ] fmt error ]
] >effect
NB[ effect do[ numInputValues numOutputValues mode ] stack is [ 2 1 output ] ]
]
Scope: note[
Stack name resolution order:
- Own set of stacks, where state and method definitions live
- Ordered list of modules. Symbol list is what is available at import time, need to explicitly refresh for updates
- A reference to `Lobby`, where iterpreter-level state lives.
Notably, -not- strictly lexical. `interpolate` provides a way to place values in from an outer scope.
Also, unless you `freeze` a quotation, a new one is allocated each time you run.
If a stack is resolved, then that should probably be cached on the current instance
]
Experimental: note[
Some code snippets that I'm noodling on.
experimental[
1 >x 2 >y 3 >z
[ x: y: z: ] from-stacks
]
]
io: module[
load-by-default
println: js: [ @ -- ] ffi[ (x) => console.log(x); ]
readln: js: [ -- @ ] ffi[ () => ; ]
]
math: module[
load-by-default
+: js: [ @ @ -- @ ] ffi[ (x, y) => x+y; ]
+: lua: [ @ @ -- @ ] ffi[ function(x, y) return x+y end ]
-: js: [ @ @ -- @ ] ffi[ (x, y) => x-y; ]
*: js: [ @ @ -- @ ] ffi[ (x, y) => x*y; ]
gt: js: [ @ @ -- @] ffi[ (a, b) => a > b; ]
lt: js: [ @ @ -- @] ffi[ (a, b) => a < b; ]
div: js: [ @ @ -- @ ] ffi[ (x, y) => x/y; ]
[ >n n. pop + n> push ] >+=
]
Point: class[
usage[
1 2 Point .fromPair >location
1 1 location .move
location .pos NB[ stack is [ 2 3 ] ]
location: drop
]
fromPair: [ @ @ -- @ ] fn[ clone do[ >y >x ] ]
init: [ -- ] method[ clone do[ 0 >x 0 >y ] ]
pos: [ -- @ @ ] method[ x> y> ]
moveByPair: [ @ @ -- ] method[ y: += x: += ]
move: [ x y -- ] method[ your[ x> y> ] moveByPair ]
]
| 1 | title[ StackTalk ] |
| 2 | |
| 3 | "Stack Basics" note[ |
| 4 | |
| 5 | An object is a collection of named stacks |
| 6 | A quotation is a malleable list of code symbols, delimited by [ and ] |
| 7 | Strings can be written two ways: |
| 8 | |
| 9 | "This is a conventional string" |
| 10 | this-is-a-symbol-string: |
| 11 | |
| 12 | There are 4 baseline stack operations: |
| 13 | |
| 14 | `$value $stack push` |
| 15 | `$stack pop` |
| 16 | `$stack peek` |
| 17 | `$stack run` |
| 18 | |
| 19 | These let you manipulate arbitrarily named stacks. |
| 20 | `run` is a bit special. It'll run top of $stack, if it is a |
| 21 | quotation, otherwise it acts like peek |
| 22 | |
| 23 | There are shortcuts for these operations: |
| 24 | |
| 25 | [ 1 x: push ] can be writtn as [ 1 >x ] |
| 26 | [ x: peek ] can be written as [ x. ] when you need no ambiguity |
| 27 | [ x: pop ] can be written as [ x> ] |
| 28 | [ x: run ] can be written as [ x ] |
| 29 | |
| 30 | ] |
| 31 | |
| 32 | "Quotation suffix autoswap" note[ |
| 33 | This one is a little inspired by https://knucklecracker.com/wiki/doku.php?id=crpl:overview#warp_notation, |
| 34 | but is ultimately a bit less generalized. |
| 35 | |
| 36 | I anticipate that quotations will be modified by a lot of words. Because of this, and because |
| 37 | I think it reads better in a lot of cases, there's another rewrite |
| 38 | |
| 39 | [ 1 [ me> 1 + >me ] do ] can be written as [ 1 do[ me> 1 + >me ] ] |
| 40 | |
| 41 | This is how `note` has been working. |
| 42 | |
| 43 | This doesn't generalize to arbitrary word movement, just for quotations. |
| 44 | ] |
| 45 | |
| 46 | |
| 47 | Objects: note[ |
| 48 | |
| 49 | The current Object/scope is the top of the `me:` stack. |
| 50 | |
| 51 | `do` executes the quotation inside the scope of object below |
| 52 | it in the stack. |
| 53 | |
| 54 | `$subject $quotation do` |
| 55 | |
| 56 | do single command Shorthand: |
| 57 | |
| 58 | [ AnObject [ aThing ] do ] can be written as [ AnObject .aThing ] |
| 59 | |
| 60 | You can use an existing object as a starting point for one of your own via `clone` |
| 61 | |
| 62 | [ 0 0 Object clone do[ >y >x ] >my2dPoint ] |
| 63 | ] |
| 64 | |
| 65 | Quotations: note[ |
| 66 | Quotations are a swiss-army-knife of a code structure |
| 67 | |
| 68 | You can call `string` on them to get their contents. |
| 69 | [ [ a thing ] .string NB[ stack is " a thing " ] ] |
| 70 | |
| 71 | `interpolate` will copy values from the containing scope based on $names |
| 72 | [ 1 >a 2 >b interpolate[ $a $b + ] NB[ stack is [ 1 2 + ] ] |
| 73 | |
| 74 | Objects copied this way are copied by reference, rather than deep cloned. |
| 75 | |
| 76 | You can get the list of symbols from a quotation |
| 77 | code[ |
| 78 | |
| 79 | [ @ @ -- @ ] symbols each[ println ] |
| 80 | NB[ print output: |
| 81 | "@" |
| 82 | "@" |
| 83 | "--" |
| 84 | "@" |
| 85 | ] |
| 86 | ] |
| 87 | |
| 88 | You can supply an interpretation ruleset, on the left side, you have patterns, on the right, consequent actions |
| 89 | The patterns match against one or more symbols (as fetched by `symbols`). |
| 90 | |
| 91 | [ @ @ -- @ ] obj[ 0 >numInputValues 0 >numOutputValues input: >mode ] |
| 92 | interperet[ |
| 93 | @ [ input: mode ] -> [ numInputValues: inc ] |
| 94 | -- [ input: mode ] -> [ output: >mode ] |
| 95 | @ [ output: mode ] -> [ numOutputValues: inc ] |
| 96 | * -> [ [ "Unrecogized symbol" _ ] fmt error ] |
| 97 | ] >effect |
| 98 | NB[ effect do[ numInputValues numOutputValues mode ] stack is [ 2 1 output ] ] |
| 99 | ] |
| 100 | |
| 101 | Scope: note[ |
| 102 | |
| 103 | Stack name resolution order: |
| 104 | - Own set of stacks, where state and method definitions live |
| 105 | - Ordered list of modules. Symbol list is what is available at import time, need to explicitly refresh for updates |
| 106 | - A reference to `Lobby`, where iterpreter-level state lives. |
| 107 | |
| 108 | Notably, -not- strictly lexical. `interpolate` provides a way to place values in from an outer scope. |
| 109 | Also, unless you `freeze` a quotation, a new one is allocated each time you run. |
| 110 | |
| 111 | If a stack is resolved, then that should probably be cached on the current instance |
| 112 | ] |
| 113 | |
| 114 | |
| 115 | Experimental: note[ |
| 116 | Some code snippets that I'm noodling on. |
| 117 | |
| 118 | experimental[ |
| 119 | 1 >x 2 >y 3 >z |
| 120 | [ x: y: z: ] from-stacks |
| 121 | ] |
| 122 | ] |
| 123 | |
| 124 | io: module[ |
| 125 | load-by-default |
| 126 | println: js: [ @ -- ] ffi[ (x) => console.log(x); ] |
| 127 | readln: js: [ -- @ ] ffi[ () => ; ] |
| 128 | ] |
| 129 | |
| 130 | math: module[ |
| 131 | load-by-default |
| 132 | |
| 133 | +: js: [ @ @ -- @ ] ffi[ (x, y) => x+y; ] |
| 134 | +: lua: [ @ @ -- @ ] ffi[ function(x, y) return x+y end ] |
| 135 | -: js: [ @ @ -- @ ] ffi[ (x, y) => x-y; ] |
| 136 | *: js: [ @ @ -- @ ] ffi[ (x, y) => x*y; ] |
| 137 | gt: js: [ @ @ -- @] ffi[ (a, b) => a > b; ] |
| 138 | lt: js: [ @ @ -- @] ffi[ (a, b) => a < b; ] |
| 139 | div: js: [ @ @ -- @ ] ffi[ (x, y) => x/y; ] |
| 140 | [ >n n. pop + n> push ] >+= |
| 141 | ] |
| 142 | |
| 143 | Point: class[ |
| 144 | usage[ |
| 145 | 1 2 Point .fromPair >location |
| 146 | 1 1 location .move |
| 147 | location .pos NB[ stack is [ 2 3 ] ] |
| 148 | location: drop |
| 149 | ] |
| 150 | |
| 151 | fromPair: [ @ @ -- @ ] fn[ clone do[ >y >x ] ] |
| 152 | init: [ -- ] method[ clone do[ 0 >x 0 >y ] ] |
| 153 | pos: [ -- @ @ ] method[ x> y> ] |
| 154 | moveByPair: [ @ @ -- ] method[ y: += x: += ] |
| 155 | move: [ x y -- ] method[ your[ x> y> ] moveByPair ] |
| 156 | ] |
| 157 |