The LogoInterpreter remains, as a singleton for any one Logo session (not sure why you'd want totally different interpreters, but I suppose it remains a possibility)
It has a set of named processes, including one "main" process
Routines belong to the interpreter, i.e., they are always global
Property lists and other named global resources also belong to the interpreter
Then there's a design question about scoping. It also relates some to how processes are launched. For instance, let's imagine FOREVER always launches a process (like in MicroWorlds), then you can imagine this:
to squares :size
forever [pu setxy 400 - random 800 400 - random 800 square :size]
end
Then if you call SQUARES 100 the routine would immediately return while launching that process. But in this case the routine needs to be closed over the local variable :SIZE. (Or closed over the value of :SIZE? E.g., if you add MAKE "SIZE 50 after the FOREVER would it affect the square sizes?)
So I can't quite decide if the process should get the scopes when it was launched (a copy of the list), or maybe a copy of the scopes? And would it create a new scope? You might imagine:
to squares
make "size 100
forever [square :size wait 100]
onkey "up [make "size :size + 10]
onkey "down [make "size :size - 10]
end
Should they all be running in the same scope? Presumably the ONKEY handlers would run in their own process as well...? This makes me think the new processes should get the exact list of scopes when the process is started, not copies, nor should they add new local scopes. Though maybe how MAKE works (as opposed to LOCAL/LOCALMAKE) makes this less concerning.
For the processes to bind to the local scope, we need some sort of turn-list-into-a-callback routine. For instance ONKEY here would have to call that, because probably the handlers would only be invoked after SQUARES returned. (FOREVER doesn't encounter this because it would start to call its argument before SQUARES is allowed to continue.) Ah, the problems of not having explicit lambdas or lexical scope...
Then there's the separate question of "objects", such as multiple turtles. I would suggest these also exist in the main interpreter, as global named resources. The process however would have a property for the "active" turtle.
I think processes should have a name (like P1, P2, etc), some aliases (like [square :size wait 100] – this is how MicroWorlds addresses naming, which gives a predictable way to get to a process if you don't capture the name), and a reason. The thing that launched the process would also assign the reason, which would be a description – probably the way the process was invoked, maybe we could use some private interpreter knowledge to improve the description further.
A proposal on processes:
Then there's a design question about scoping. It also relates some to how processes are launched. For instance, let's imagine FOREVER always launches a process (like in MicroWorlds), then you can imagine this:
Then if you call SQUARES 100 the routine would immediately return while launching that process. But in this case the routine needs to be closed over the local variable :SIZE. (Or closed over the value of :SIZE? E.g., if you add MAKE "SIZE 50 after the FOREVER would it affect the square sizes?)
So I can't quite decide if the process should get the scopes when it was launched (a copy of the list), or maybe a copy of the scopes? And would it create a new scope? You might imagine:
Should they all be running in the same scope? Presumably the ONKEY handlers would run in their own process as well...? This makes me think the new processes should get the exact list of scopes when the process is started, not copies, nor should they add new local scopes. Though maybe how MAKE works (as opposed to LOCAL/LOCALMAKE) makes this less concerning.
For the processes to bind to the local scope, we need some sort of turn-list-into-a-callback routine. For instance ONKEY here would have to call that, because probably the handlers would only be invoked after SQUARES returned. (FOREVER doesn't encounter this because it would start to call its argument before SQUARES is allowed to continue.) Ah, the problems of not having explicit lambdas or lexical scope...
Then there's the separate question of "objects", such as multiple turtles. I would suggest these also exist in the main interpreter, as global named resources. The process however would have a property for the "active" turtle.
I think processes should have a name (like P1, P2, etc), some aliases (like
[square :size wait 100]
– this is how MicroWorlds addresses naming, which gives a predictable way to get to a process if you don't capture the name), and a reason. The thing that launched the process would also assign the reason, which would be a description – probably the way the process was invoked, maybe we could use some private interpreter knowledge to improve the description further.