Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance: Named functions #15

Closed
dpharris opened this issue Feb 27, 2016 · 17 comments
Closed

Enhance: Named functions #15

dpharris opened this issue Feb 27, 2016 · 17 comments

Comments

@dpharris
Copy link

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.

@mikaelpatel
Copy link
Owner

I actually plan to add something just like that but with full names. Was thinking of a twist on the Postscript syntax.

{ block }\foo
_foo

But this is basically what you are suggesting. Nice to see that you have already caught on how this tiny script language works!

{rsos>sr<|~}\within
10,5,100_within

This has a dependency to storing scripts in PROGMEM or EEMEM.

@dpharris
Copy link
Author

Yes, I like your plan to use PS syntax. I was trying to maintain the small footprint of the scripts by using songle chars - but your plan doesn't limit that.

@dpharris
Copy link
Author

I started to modify your code so that I could define functions by storing the block-address in a variable.

Then I realized that you already have this!!! Its documented in the Variable section.

c{12.}2!,,2@x,,5{2@x}l

clear { 12 print } 2! 5 { 2@x } loop

works, too.

@mikaelpatel
Copy link
Owner

First steps towards named functions; copy code block to heap. Please see commit c3a61b1.

@mikaelpatel
Copy link
Owner

New format for allocating a code block. \ gets the length of the block, a copies the block to the heap and pushes the new block address.

 { code-block }\a      -- allocate on heap
 { code-block}\a0!     -- assign variable with allocated block address
 0@x                   -- read variable and execute block

@dpharris
Copy link
Author

Why did you add \and a, rather than a single operator?

@mikaelpatel
Copy link
Owner

It is a symmetry thing :). \ being an outer interpreter function and a an inner.

alloc ( buf1 len -- buf2 )
free (buf -- )

But things will change along the road. Need to work with it a while to see what "feels natural" and gives a good flow.

Alloc and free may soon be removed when introducing a traditional forth here and alloc. The variable table and the stack would become the top and bottom of a memory area for the shell. The input buffer could be at here. In that case there is no need for a copy. Simply moving dp dictionary pointer will be sufficient. This is actually one of the reasons for changing the stack direction (in the latest commits).

@dpharris
Copy link
Author

OK. I do like the 'ultimate simplicity' of Arduino-Shell so far. Adding
extras in may ruin that .. but I respect your long association with forth,
so you will have a better feel for it.
You are planning to include function names inline? This keeps the whole
thing in a set part of memory.

On Sun, Feb 28, 2016 at 12:00 PM, Mikael Patel notifications@github.com
wrote:

It is a symmetry thing :). \ being an outer interpreter function and a an
inner.

alloc ( buf1 len -- buf2 )
free (buf -- )

But things will change along the road. Need to work with it a while to see
what "feels natural" and gives a good flow.

Alloc and free may soon be removed when introducing a traditional forth
here and alloc. The variable table and the stack would become the top and
bottom of a memory area for the shell. The input buffer could be at here.
In that case there is no need for a copy. Simply moving dp dictionary
pointer will be sufficient. This is actually one of the reasons for
changing the stack direction (in the latest commits).


Reply to this email directly or view it on GitHub
#15 (comment)
.

@mikaelpatel
Copy link
Owner

Reopening this issue as it is soon time to implement. Current proposed design and syntax for named functions is:

:name code-block; 
\name

This is more of less the forth style but with an explicit call operator "". This would replace the block allocate/deallocate.

The ":" operator would add the "name" to a dictionary and copy the code block until ";". The "" is run-time lookup and execute of the "name". To make this even more interesting the "name" is associated with a variable and given the type code-block. This will give an internal mechanism much like forth "create-does>".

@mikaelpatel mikaelpatel reopened this Feb 29, 2016
@dpharris
Copy link
Author

Of the top:
Is this copying to dict space?
Do you need ; if you have {}? You could have {...}:name!
Is \name a reference? So \name@x?
I guess f becomes forget: \name f

@mikaelpatel
Copy link
Owner

Yes, and no. It has to do with how much logic is behind the "\name". In forth this depends on the type of name; colon, variable, constant and create-does> to generalize this. The dict space is often just a linear address space, and "forget" steps back the allocation point.

The construct ":name" is a nice postfix notation and might work well with the control structures. My concern is the state of the parse.

In my original proposal "\name" is a lookup and execute. "\name@" implies that "\name" is actually a lookup and push of an address in the variable vector. In that case the block allocate and deallocate are still needed.

The ":name code-block;" does away with all that.

@dpharris
Copy link
Author

dpharris commented Mar 2, 2016

So, :fnc ... ; and \fnc and reclaim \ and a. Sounds good.
Works for naming everything:

  • variables: :nitems 12; and \nitems.
  • vectors: :event0 [12 34 45 56 67 78];
    I like it.

@dpharris
Copy link
Author

dpharris commented Mar 2, 2016

Please consider calling a trap on failure of the Shell to find a matching dict entry. This would allow quite easy extensions with useful names.
\sqrt \spi

Please also consider allowing any characters in a function name, as this would allow:

  • [] " *+
    This would probably require white-space after the name definition and use.

@mikaelpatel
Copy link
Owner

First version up and running. A small step forward.

{ code-block };\fun!
\fun@x
\fun:

10 \x !
\x @ 

Names are only alpha characters (for now).

@dpharris
Copy link
Author

dpharris commented Mar 2, 2016

Boy, you are a moving target :-) (I discovered t-->Z, c -->C, S)
Here is SHOW '{v{uXv 1+ uX0#}w'}vm using my X trap.
I defined \add and 0 as functions, and discovered that the names assign in order to the vars. I think that is ok.

Perhaps a different 'address-space' would be better, but I will have to play with it a bit. Might work very well in my application, since I plan to have multiple scripts, one for each event, and each of those will want to have parameters. Now I can name them, which will make life easier for the users.

@mikaelpatel
Copy link
Owner

Boy, you are a moving target

Yepp, it is all about refactoring.

BW: c@, <c@ and c! will enter the word list with other string functions when things start to be more stable. The printable ASCII characters are almost covered. Some logical changes remain. I was reserving uppercase characters for the Arduino function but now it also included typical extensions such as C(lear), T(race toggle) and S(tack dump). Also I need to add a level of configuration so that the instructions can be add/removed depending on the applications.

For most users the address of the variables/functions is not really of interest. Also in contrast to forth the dictionary is searched from first entry to last (latest). And there is only one entry per name.

There is a simple transformation from \name to variable address which gives possible compression. The block scan is an issue for large blocks (as discussed before). There are a few possible optimizations; 1) cache resolved addresses (end of block), 2) replace "{" with offset (it is always forward and there are 128 8-bit values available for that, i.e. replace "{" with 0x80+offset).

@dpharris
Copy link
Author

dpharris commented Mar 2, 2016

Hmmm -- the simplicity may be fading. At the moment I am impressed that
the ascii script = tokens.

If you exchange a '{' with a 0x80+offset, then the script is no longer
simple ascii (although easy to replace >0x7F with '{', I suppose, when
displaying).

Agree, the use of variable 0-n is useful, if compression is required.

I kind of liked your idea of (forth-like) :fnc ... ; and \fnc executing
immediately. One can always use 0@, 0@x and 0! if one wants to mess with
the script.

My + + forms are problematic somewhat, as they would require what-space
to distinguish them. One could include ',' in the white-space category, so
something like [2 3 4 5 6] {
} \f+,. , where \f+ takes an block, applies
to each item and sums the result.

I expect you have a gameplay, and probably too complicated to explain ... I
will just follow along :-)

Great work.

@mikaelpatel mikaelpatel changed the title Named functions Enhance: Named functions Mar 17, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants