Thanks a lot for taking the time to respond.

Your response was really helpful. Nonetheless, it actually made me quite a
bit more confused about row-variable stack effects and runtime calls.
I actually wrote a huge response with quite a few questions and, while I
was writing it, the documentation digging I had to do to argument my
questions actually got me to respond to them completely.

Furthermore, with this improved understanding, I found a solution that
satisfied my initial requirements and which is as simple as using a single
quotation.

H{ { 0 [ parse-x eval-x ] } ... }


As my interface is designed to have an lc3 at the top of the stack
permanently and each parser-evaluator pair goes from an lc3 instruction to
a modified lc3, in conjunction the pair always has ( x x -- x ) stack
effect and only requires that the associated words are internally
compatible ( which is always true as I'm manually making the pairs ).

Now, I've made some tries and everything seems to work correctly, am I
right in thinking that I should not incur in any problem as long as the
invariants ( parsers go from x to n-args, evaluators go from lc3 n-args to
lc3, parser-evaluator pairs always have the same number of n-args)?

So thanks a lot, especially for instilling in me a constructive train of
thoughts which helped me learn a lot.

Best Regards,
Di Sera Luca


Il giorno sab 1 giu 2019 alle ore 15:35 John Benediktsson <mrj...@gmail.com>
ha scritto:

> You will need at some point to specify the arity of your functions.
>
> You can call quotations "dynamically" like this... but if the stack
> checker can't infer what the quotation's stack effect is, you need to
> specify in the ``call(`` what the effect is so that it will be checked at
> runtime:
>
>     IN: scratchpad : foo ( x quot -- y ) call( x -- y ) ;
>
>     IN: scratchpad 2 [ sq ] foo .
>     4
>
> Seems like you would just need to specify in your opcode map what the
> arity of your words are and do something like:
>
>     CONSTANT: ops H{
>         { "add" { [ + ] 2 } }
>         { "sq" { [ sq ] 1 } }
>     }
>
>     : foo ( stack opcode -- output )
>         '[ _ ops at first2 {
>                 { 1 [ call( x -- y ) ] }
>                 { 2 [ call( x y -- z ) ] }
>             } case
>         ] with-datastack ;
>
>     IN: scratchpad { 2 } "sq" foo .
>     { 4 }
>
>     IN: scratchpad { 2 3 } "add" foo .
>     { 5 }
>
> There are a few other ways / approaches but basically that's an idea for
> you...
>
> Hope it helps!
>
>
>
> On Fri, May 31, 2019 at 8:47 AM Luca Di Sera <bloodtype.si...@gmail.com>
> wrote:
>
>> I'm working on an implementation of the lc3 -vm (
>> https://justinmeiners.github.io/lc3-vm/ ).
>>
>> This a basic didactical architecture.
>>
>> In the code, I have a TUPLE: that is used to keep the state of the vm.
>>
>> TUPLE: lc3 { ram array } { registers array } { pc integer } { cond
>>> bit-array } ;
>>>
>>
>> An instance of this TUPLE is passed around by some of the code to execute
>> instructions and change the internal state.
>>
>> Instructions are coded as 16bit values where the highest 4 bits represent
>> an op-code that identifies the instruction to execute and the rest of the
>> bits contain informations about the necessary data to execute it.
>> In my code I'm using a map of pairs to dispatch to the correct (
>> quotated- ) words depending on the opcode.
>>
>> CONSTANT: OPCODE_MAP H{
>>> { 0 { [ parse-br ] [ eval-br ] } }
>>> { 1 "add" }
>>> { 2 "ld" }
>>> { 3 "st" }
>>> { 4 "jsr" }
>>> { 5 "and" }
>>> { 6 "ldr" }
>>> { 7 "str" }
>>> { 8 "rti" }
>>> { 9 "not" }
>>> { 10 "ldi" }
>>> { 11 "sti" }
>>> { 12 "jmp" }
>>> { 14 "lea" }
>>> { 15 "trap" }
>>> }
>>>
>>> : parser-evaluator ( opcode -- parser evaluator )
>>> OPCODE_MAP at [ first ] [ second ] bi ;
>>>
>>
>> The strings are there as temporary values that I still have to build.
>>
>> Not all instructions encode informations in the same way. Some of them
>> may include 4 pieces of informations of different width and type and some
>> others may contain more or less of them.
>> To correctly retrieve informations and to execute the correct instruction
>> I'm using those parser-evaluator pairs.
>>
>> All parsers, which cut instructions into the correct pieces of
>> informations, expects the stack to have an instruction at its top to
>> consume while pushing a variable number of values in its place.
>> All evaluators, which actually execute the given instruction modifying
>> the state of an lc3,  expects n values on the stack to consume and will
>> push-out a modified lc3.
>>
>> Now, those parser-evaluator pairs are call( [ed] at runtime.
>> After many tries, I was able to construct a piece of code that would
>> compile ( Stack-effects are not completely clear to me yet ).
>> Unfortunately, when a parser-evaluator pair is actually called the program
>> will stop as the expressed stack effect of call( is considered incorrect.
>>
>> : _eval ( lc3 parser: ( instruction -- ..a ) evaluator: ( ..a -- lc3 ) --
>>> lc3 )
>>> [ call( instruction -- ..a ) ] [ call( ..a -- lc3 ) ] bi* ; inline
>>>
>>
>> (U) Quotation: [ set-namestack init-catchstack self quot>> call => stop ]
>>> (O) Word: listener-thread
>>> (O) Word: listener
>>> (O) Word: (listener)
>>> (O) Word: listener-step
>>> (U) Quotation: [
>>>         [ ~quotation~ dip swap ~quotation~ dip ] dip swap
>>>         [ call get-datastack ] dip => swap [ set-datastack ] dip
>>>     ]
>>> (U) Quotation: [ call => get-datastack ]
>>> (O) Word: eval
>>> (O) Word: wrong-values
>>> (O) Method: M\ object throw
>>> (U) Quotation: [
>>>         OBJ-CURRENT-THREAD special-object error-thread set-global
>>>         current-continuation => error-continuation set-global
>>>         [ original-error set-global ] [ rethrow ] bi
>>>     ]
>>>
>>
>> After some tries, I'm at a kind of roadblock that I seem unable to
>> untangle.
>> How can I express, if at all possible, this kind of polymorphism in
>> factor ? What are some alternative ways to produce the same effect ?
>>
>> For reference this is the relevant code:
>>
>> USING: lc3-vm.core.lc3.private lc3-vm.core.lc3 sequences bit-arrays
>>> locals kernel assocs ;
>>> IN: lc3-vm.core.instructions
>>>
>>> <PRIVATE
>>>
>>> CONSTANT: OPCODE_LENGHT 4
>>>
>>> : instruction>opcode ( instruction -- instruction opcode )
>>> OPCODE_LENGHT cut* bit-array>integer ;
>>>
>>> : parse-br ( instruction -- n z p offset )
>>> 1 cut 1 cut 1 cut [ [ first ] tri@ ] dip bit-array>integer ;
>>>
>>> : n-and-cond-n? ( lc3 n -- ? )
>>> [ cond-n? ] dip and ;
>>>
>>> : z-and-cond-z? ( lc3 z -- ? )
>>> [ cond-z? ] dip and ;
>>>
>>> : p-and-cond-p? ( lc3 p -- ? )
>>> [ cond-p? ] dip and ;
>>>
>>> :: br-should-jump ( lc3 n z p -- ? )
>>> lc3 n n-and-cond-n? lc3 z z-and-cond-z? lc3 p p-and-cond-p? or or ;
>>>
>>> :: eval-br ( lc3 n z p offset -- lc3 )
>>> lc3 n z p br-should-jump [ lc3 offset jump-by ] [ lc3 ] if ;
>>>
>>> CONSTANT: OPCODE_MAP H{
>>> { 0 { [ parse-br ] [ eval-br ] } }
>>> { 1 "add" }
>>> { 2 "ld" }
>>> { 3 "st" }
>>> { 4 "jsr" }
>>> { 5 "and" }
>>> { 6 "ldr" }
>>> { 7 "str" }
>>> { 8 "rti" }
>>> { 9 "not" }
>>> { 10 "ldi" }
>>> { 11 "sti" }
>>> { 12 "jmp" }
>>> { 14 "lea" }
>>> { 15 "trap" }
>>> }
>>>
>>> : parser-evaluator ( opcode -- parser evaluator )
>>> OPCODE_MAP at [ first ] [ second ] bi ;
>>>
>>>
>>> : _eval ( lc3 parser: ( instruction -- ..a ) evaluator: ( ..a -- lc3 )
>>> -- lc3 )
>>> [ call( instruction -- ..a ) ] [ call( ..a -- lc3 ) ] bi* ; inline
>>>
>>> PRIVATE>
>>>
>>> ALIAS: instruction 16bit
>>>
>>> : eval ( instruction -- lc3 )
>>> instruction>opcode parser-evaluator _eval ;
>>>
>>
>> A preemptive thanks to anyone who will take the time to help me get a
>> better understanding of this issue.
>>
>> Best Regards,
>> Di Sera Luca
>> _______________________________________________
>> Factor-talk mailing list
>> Factor-talk@lists.sourceforge.net
>> https://lists.sourceforge.net/lists/listinfo/factor-talk
>>
> _______________________________________________
> Factor-talk mailing list
> Factor-talk@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/factor-talk
>
_______________________________________________
Factor-talk mailing list
Factor-talk@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/factor-talk

Reply via email to