mikaelpatel / arduino-shell Goto Github PK
View Code? Open in Web Editor NEWRPN Postscript/Forth Command Shell for Arduino
RPN Postscript/Forth Command Shell for Arduino
Your change to loops broke the example.
This works:
[1,2,3] 0 1 rotate { drop + } loop
or:
[1,2,3]0,1r{d+}l
A larger list is nicer: [1,2,3,4,5,6,7,8]0,1r{d+}l
This would be useful. Possible do it now, but messy:
2@ d0={(1st)}i d1={(2nd)i 2d={(3rd)}i
Alternately could use stack marker and 'C' perhaps:
[{(1st)}{(2nd)}{(3rd)}{(4th)}]2@C
C would need to check selector range, execute the appropriate block, and delete the block addresses from the stack.
May be guilding the lily.
SPI transfer function; spi-transfer ( data0 -- data1 ).
cs low
data spi-transfer
cs high
Remove ability to execute a simple operation code. Merge the two Shell execute() member functions.
Remove all usage of dynamic allocation of memory. Move essential data structure to PROGMEM and EEPROM.
The Memory virtual member function read() is the most common call from the interpreter. There is a high overhead with a virtual member function call. Any improvement in this function will scale in interpreter overall performance.
Great work. I have often played with doing something like this.
Can you add a comment on how to use variables?
Do you have a compiler / decompiler to go between the expanded forms to compressed forms?
And do not recursively call execute().
Adding a return address stack will also allow yield() to be implemented as a return from execute() will ip on stack. This will require a resume() function to pop the ip and continue the interpreter.
Add the forth "words" function or a primitive to access and print the name field of a variable.
Use the traditional forth syntax (xxxxxx).
I found a nice case statement form:
c {+-*+*+}\1- {uX u'+={(add )}i u'-={(minus )}i '*={(times )}i 1+}l
This outputs: "add minus times add times add"
I added a X trap that pops a char onto the stack from the {} list.
A set of benchmarks are needed to allow measurement of performance tuning efforts.
The operation codes for frames, parameters, variable lookup and escape could be more logical.
The old syntax:
{2$2_@1_@-2};\swap!
3,4\swap:
would become:
{2\2$@1$@-2\};`swap!
3,4`swap:
I am not sure I fully understand stack markers [].
[6 34$I]
would read 6 bytes from I2C device 34, and leaves 6 items on the stack with a count 6 on top, useful for future processing.
How does that differ from just:
6 34 $I 6
?
I will go and reread PS (last time 25 yrs ago!).
As scripts may run from SRAM, EEPROM and PROGMEM the synthetic linear address should be shown in the trace instead of the local address.
n$ pushes frame-pointer onto stack.
n? Retrieves parameter n
It can also ghe stack above the fp,
Essentially giving local-variables.
-n $ copies removes n stack contents below f and
Moves the top items down.
I like this a lot, can give quite a nice all syntax:
c{$6 7 8 2?. 6?. -4$}0! [1 2 3 4] 0@x
==> 6 7 8
Note the first $ eats the []'s length, but one still needs the -4$
Note it allows for local variables, too.
I tried implementing 'p' as:
case 'p': // xn..x1 y i -- xn..y..x1 xn | poke
n = pop();
*(m_fp - n)=pop();
break;
This lets one poke into the frame, including locals:
c{$ 6,7,8 2?. 88,5p 99,2p -4$}0! [1 2 3 4] 0@x
==> 88 7 8
It should be possible to set a variable or function from the sketch. This allows the application to define a set of scripts.
shell.set(name, value);
shell.set(name, script);
Hi,
I had a couple of ideas and was wondering if you guys have either already considered them or already done them.
Umbilical: On a host machine a use enters scripts interactively. These are 'compiled' and the results passed to the Arduino relieving it of compilation duties, but still providing an interactive environment.
Compiler. Take a script and produce the corresponding .ino file for compiling onto the Arduino.
I suspect that 2) would be fairly simple.
Comment welcome :)
Andrew
I2C requires at least two function; twi-read ( n addr -- x1 ... xn) and twi-write ( x1 ... xn n addr -- ). Many driver functions have the form;
reg 1 addr twi-write n addr twi-read // read a register
val reg 2 addr twi-write // write a register
Can you explain how you saw '$' working?
I had assumed that $ sucked in the next char and sent that to the trap(char) function. I messed with the code and got that to work. However, ...
It seems like you are trying for a more general mechanism that just traps to a trap(char) function, and then the trap function can do anything (within reason). Is it allowed to play with the stream, i.e. peek and poke it?
I see a new t(timeout) token. I need this in my app!
This works: 13O 0{1000,0t{{13L0}{13H1}e}i T}w
Or: 13O {1000,0t{13X}iT}w
I have been using:
if(MIllis()>next) { .... next+=period; } // this is slightly faster, and gives consistent period
[[ roll-over is a problem, and more of a problem with Shell, since M is only a word.
The math should be something like:
if( (uint16_t)(M-next)>0x3FFF ) ... when using uint16_t (I think)
Or
if( (int16_t)(M-next)>0 ) ... if using signed arithmetic (I think)
]]
While this sounds like a good idea, and might make writing and understanding the scripts, it should be a secondary project -- it has a good chance of quickly complicating this project.
A suggestion for generalizing CLEAR:
You have:
c | xn..x1 -- | clear | ABORT
and:
j | xn..x1 -- xn..x1 n | stack depth | DEPTH
I wonder if it would be better:
c | xn+1xn..x1 n -- xn+1 | clear n items | CLEAR
This would let one do:
to clear whole stack:
jc
to remove a []:
[1 34 23 45 2@]c
Forth functions "c@", "<c@" and "c!" should be part of the instruction set. This may require reimplementing "@" and "!" to use memory addresses instead of shell memory space only (variables/stack index). The alternative is to create a small heap (a traditional dictionary with HERE and ALLOT) within the Shell object (as variables/stack).
Delegate block (and literal parse) to memory handler.
This will duplicate code but would removed function call overhead.
One example showed defining a function, and then it being used as a macro. Perhaps one could have named blocks and activate them with : as an escape character.
Eg:
{rot swap over swap > swap rot < or not};W
10 5 100 :W.
Script:
{rsos>sr<|~};W10,5,100:W.-10,5,100:W.110,5,100:W.
Obviously this impacts memory etc etc and may have complications and unintended consequencies.
Functions defined interactively should be copied to EEMEM. This would require the interpretor to understand an additional address space. In general all usage of SRAM should be reduced to a minimum.
Revert to traditional forth style but without compile state.
:name { code-block };
And call is:
`name
Or:
:name@x
Please see commit 874fba8.
Dictionary lookups (\name) are not visible in the trace.
The other demos appear to work fine.
Time to move forward with the function definition syntax:
`fun { code-block } ;
And function call:
`fun:
Some other minor changes:
c ( x1..xn n -- ) drop n elements
C ( x1..xn -- ) clear stack
Last, extension is using "_" prefix only.
The loop control structure could be improved to:
low high { loop-block } loop
And the loop block should receive the current index as top of stack.
I noticed on the 43oh group that forth has sprung forth in several forms. The SIMPL language mentioned here: http://forum.43oh.com/topic/9429-simpl-a-tiny-language-for-msp430/ looks similar to your efforts. I haven't analyzed in detail, but I like yours!
How can hex be entered? Suggestion might use X: X5ef,Xa5+.
(Would have preferred x, and X for execute.)
Numbers are only printed in decimal base.
The current dictionary is in EEPROM. A possible extension is to add an application dictionary fully in PROGMEM. There could actually be several dictionaries.
Increasing the number of entries will require a much faster lookup (i.e. cache).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.