[stack] things
spir <[email protected]>
| Newsgroups | gmane.comp.lang.concatenative |
|---|---|
| Message-ID | <20090304112148.556f73f9@o> |
Hello concatenators,
All those talks about concatenativity let me "dream" about a tiny language designed only to exhibit some properties -- or the lack of them. An attempt to have a base of concrete ;-) facts to reason.
Here a kind of informal description I wish you experimented language designers will comment & criticize; before I really start a foolish implementation. It may be written in Io (using a modified version of IoPEG, see http://code.google.com/p/iopeg/), for I'm learning this language.
Then I intend to explore how modifications will let the language get or lose this one or that one property.
======================================
-1- stack based
-2- reverse polish notation
-3- single data type: "thing"
This is a kind of tree which nodes can have any number of leaf or branch children. Or a nestable list. (If someone would try to explain me, outside the list, the difference between a tree and a recursive list -- thanks a lot ;-). Meaning something like
(x (1 (u v) 2) (a b))
or
x
<branch> # or <sequence>
1
<branch>
u
v
2
<branch>
a
b
-4- plain text data
Basically, things are internally stored as plain text the same way they are literally expressed in source code (thinking at TCL). Wich should be the Lisp-like (...) expression above.
-5- one unique "operational" primitive word: "write"
Write will take the topmost item on the stack and write it out into a tree view like shown above.
(x (1 2 (u v)) (a b)) write
==> tree view
-5- code is thing
Code is data of the type thing, too. There may be some syntactic sugar:
* To define a word -- meaning binding name to code block -- the format
name : block
maps to
(name (block))
or in Forth to
:name block;
* End of lines mark the end of a word definition. They are thus a top-level nesting separator inside a thing literal. So that
(a b c
d e f)
maps to
((abc)(def))
And
name1 : block1
name2 : block2
maps to
((name1 (block1) (name2 (block2))
* As a consequence, the stack itself could be stored as an EOL-separated text of thing literals -- instead of a list of things (?!). Pop reads the last line; push appends a new line.
-6- every action is explicitely word call
There are some "meta-primitives", first of all push and pop that must be expressed. Things read (or produced by possible future words) go into an accumulator. Push moves them from the accumulator to the top of the stack. Pop removes the topmost item. Do "does" code that should be on the stack (if the code is a defined word, it may be referenced instead).
:writeOne 1 write
in Forth could written
writeOne : 1 push write push do pop pop
If the stack is empty at start, it's empty at the end. This only to show that there is no magic -- only actions -- then I could get rid of that expliciteness. Onother options could be that words are implicitely pop-ed when read on the stack to be done (else the argument is the second item from top of the stack):
writeOne : 1 push write push do pop
Note that words can be written out like any other thing (this I like very much -- it's like in Io "myMethod code println"):
showCode : writeOne push write push do pop
-7- the interpreter can be fed with code things
As code is thing, then it can be expressed and "done" at runtime. Maybe something like (untested ;-):
writeOneTwice : (one push dup write push dup do do pop2) push do pop
Here the whole parenthesized thing is pushed as a thing, then done as code -- if ever it's valid ;-)
========================================
Only when processed with do or write or any future word, a thing will be parsed to exhibit its structure (into a list, probably). But this is then interpreter level implementation.
I would like to add primitives to access and manipulate a thing's internal data and structure. This would also allow Lisp-like or Io-like manipulation of code.
An intriguing idea is to change Thing's structure into a kind of nested record (or dict), or named tree, where nodes have keys/names/indexes. Like for instance:
(point:(kind:center position:(33 99) color(127 0 255)))
point
kind
center
position
33
99
color
127
0
255
[I do not know how to call such a mix of record and list.]
Then a word definition written as
name:(block)
directly maps to a thing literal without any word-name data item: the word's name is the top-level key of the thing.
Unnamed items would implicitely get an ordinal key:
(a:x y c:z) --> (a:x 1:y c:z)
The strange thing here is that if ever the stack is still stored and represented as a thing, then it would be a kind of record object -- wich items may be accessible by name... where does this lead ? To a kind of object forth at the base???
Still further, I could add thing parsing ability to the language itself. Then it could parse code, the interpreter could be written in itself -- except for basic primitive such as IO -- and it could even interpret itself?
denis
------
la vita e estrany