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 ] 
]
