[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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.