Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

WHILE and addition

11 views
Skip to first unread message

ais523

unread,
Oct 22, 2007, 5:22:25 AM10/22/07
to
PLEASE NOTE THIS PROGRAM READS IN TWO 16-BIT NUMBERS AND ADDS THEM
DO WRITE IN .1
DO WRITE IN .2
(1) DO COME FROM ".2~.2"~#1 WHILE :1 <- "'?.1$.2'~'"':1/.1$.
2'~#0"$#65535'"$"'"'&.1$.2'~'#0$#65535'"$#0'~#32767$#1"
DO READ OUT .1
PLEASE GIVE UP

Yes, with the great advances in CLC-INTERCAL technology (and C-
INTERCAL has caught up to a sufficient extent to be able to express
the above, which is in C-INTERCAL notation), it's now possible to fo
16-bit addition in a single statement.

Computed COME FROM is sufficiently compact that it allows the
termination condition of the loop to be written on the left of the
WHILE; operand overloading allows the right hand side to do two
assignments at once, and the arithmetic works by continuously taking
the noncarrying sum and the carries, leftshifting the carries, and
repeating the addition until there are no carries left. (It adds in
place and clobbers both one of the numbers being added and an
unrelated twospot variable, but such is INTERCAL, and besides an extra
assignment and a STASH/RETRIEVE pair can solve that problem.) (On
another note, I find computed COME FROM /much/ easier to write loops
with than NEXT/RESUME/FORGET; am I just unusual in this regard?)

Yes, I know that this may be proof that INTERCAL is now too powerful
and easy to write, but that addition above actually meets with my
approval; after all, it isn't a very obvious way to write an addition
for people unused to INTERCAL, and it isn't very easy. Besides, WHILE
introduces an entirely new form of multithreading; if there's a NEXT
in /both/ branches of the WHILE, it (at least in C-INTERCAL) leaves
two threads which have shared variables and stashes, but separate NEXT
and choicepoint stacks. (I have no idea what happens if you change a
variable in one thread and then backtrack in the other, and am
slightly worried that it may be a segfault, so I'll have to have a
look at that before the next release; I get confused thinking about
what ought to happen in such a situation, and would be happy for
someone else to suggest something.) At current, all threads share
ABSTAIN information (not a bug) and unstashed operand overloading
information (is a bug, but I think I know how to fix that) whether
created with WHILE or COME FROM; but the advantage of WHILE is that it
may allow a C-INTERCAL way to implement the splat variable that CLC-
INTERCAL has already (in such a way that errors only kill the thread,
rather than the program, if at least one thread shares variables with
the thread with the error; this seems to require at least two extra
threads to check what went wrong to come up with an error-checking
system which is errorproof itself, which is about the right level of
complexity simply to validate spelt-out IO).

--
ais523

Claudio Calvelli

unread,
Oct 22, 2007, 6:15:18 AM10/22/07
to
On 2007-10-22, ais523 <ais...@bham.ac.uk> wrote:
[...]

> (On
> another note, I find computed COME FROM /much/ easier to write loops
> with than NEXT/RESUME/FORGET; am I just unusual in this regard?)

Same here. But the, I would, wouldn't I?

> Yes, I know that this may be proof that INTERCAL is now too powerful
> and easy to write, but that addition above actually meets with my
> approval; after all, it isn't a very obvious way to write an addition
> for people unused to INTERCAL, and it isn't very easy. Besides, WHILE
> introduces an entirely new form of multithreading; if there's a NEXT
> in /both/ branches of the WHILE, it (at least in C-INTERCAL) leaves
> two threads which have shared variables and stashes, but separate NEXT
> and choicepoint stacks. (I have no idea what happens if you change a
> variable in one thread and then backtrack in the other, and am
> slightly worried that it may be a segfault, so I'll have to have a
> look at that before the next release; I get confused thinking about
> what ought to happen in such a situation, and would be happy for
> someone else to suggest something.)

The situation is more complicated in CLC-INTERCAL due to the two stacks
system (NEXT and lectures have independent stacks, and you can return
from one while still inside the other, if that makes any sense).
I wouldn't dare thinking what happens when you do something like

RESUME #1 WHILE FINISH LECTURE

so I'll now officially define CLC-INTERCAL's documented behaviour in this
sort of situation as "whatever happens when you do it".

C

--
The address in the "From" header won't work. Email to "usenet" at "intercal" dot
"dyn-o-saur" dot "com" may or may not reach me, depending on how far it manages
to go through the spam filter, and other conditions which I won't disclose.

ais523

unread,
Oct 23, 2007, 6:13:15 AM10/23/07
to
On Oct 22, 11:15 am, Claudio Calvelli

<qwertyu...@asdfghjkl.zxcvbnm.not> wrote:
> I wouldn't dare thinking what happens when you do something like
>
> RESUME #1 WHILE FINISH LECTURE
>
> so I'll now officially define CLC-INTERCAL's documented behaviour in this
> sort of situation as "whatever happens when you do it".
>
I looked into the matter with respect to C-INTERCAL and decided:
- Officially defining the behaviour as a segfault, which is indeed
what happened when I tried some test code (DO (1) NEXT WHILE (2) NEXT,
followed by MAYBE and GO BACK in both branches), would be funny, but
not all computer systems are capable of segfaulting and besides, it's
nice to have defined behaviour it's actually possible to do something
with
- The behaviour that I found when I tested was due to pre-existing
bugs in the multithreader and backtracking code which had somehow not
been caught so far, and correcting those bugs changed the behaviour
anyway, and I had more than one choice about how to do it
- so I may as well pick something reasonably consistent with what the
compiler was trying to do anyway and define that as the official C-
INTERCAL behaviour.

So the official behaviour is:

A WHILE command starts two threads (the original thread that ran that
command and a new one), one of which runs the command to the left and
one of which runs the command to the right. Any line number applies to
the left-hand command, not the WHILE as a whole, which is a
metalanguage construct. NEXTING FROM, ABSTAINING FROM or similar
behaviour with respect to the WHILE itself is impossible, although
it's certainly possible to abstain from either of its operands or next
from the left operands (and abstaining from the left operand has much
the same effect as abstaining from the WHILE itself; the right-hand
thread deliberately takes a bit of time to get started so that this
behaviour happens). The right-command thread starts just before the
left command is run (so NEXTing, etc., directly to the left command
will not start that loop in the first place); if that command finishes
(which may be almost immediately for something like CALCULATE, or take
a long time for something like NEXT), that thread loops and reruns
that command as long as the left command has not finished; COMING FROM
that command, or a NEXT/NEXT FROM from/aiming at that command, doesn't
count as finishing that command until it is RESUMEd back to (if
possible; if it's come from, that command can never end and the right-
hand loop will continue forever). A WHILE command itself exists across
all threads of a multithreaded program in a way; for each left-hand
command that ends (in any thread), the next time a right-hand command
ends it will cause the thread it's looping in to end, regardless of
whether that thread corresponds to the thread in which the left-hand
command ended. (As well as a right-hand command ending, there's also
the possibility that it never got started; there is a delay before the
right-hand command runs during which a left-hand command ending can
prevent the right-hand thread starting in the first place; this counts
as the same sort of event as terminating a right-hand loop, and can
substitute for it anywhere a right-hand command ending is mentioned.)
There is one exception, in that if two or more left-hand commands end
in a space of time in which no right-hand commands for that WHILE
ends, they together only cause one right-hand command to end. [This
particular behaviour is one of my main concessions to the way the
compiler actually behaves, as opposed to the way it 'ought' to behave
in some sense; it would be more orthogonal and logical to end the same
number of right-hand threads as left-hand threads in this situation,
but as this INTERCAL I'm going with the counterintuitive version of
the behaviour documented here.]

The two threads produced by a WHILE (the original thread and a new
copy of it) have more in common than ordinary INTERCAL threads created
by COME FROM; ordinary threads share only ABSTAIN/REINSTATE
information, whereas the WHILE-produced threads count as 'woven'
threads which also share variables and stashes. (They still have
separate instruction pointers, separate IP stacks, such as the NEXT
stack, and separate choicepoint lists. Overloading information in my
current working version of C-INTERCAL (and in the released version
1.26) is shared between all threads, but this is a bug which I intend
to fix before the next release, and weaving ought to also share
overloading information.) Being woven is a relationship between two or
more threads, rather than an attribute of a thread.

Ordinary multithreading cannot create woven threads. When threads are
created by multiple COME FROMs from an original thread, which was
woven with at least one other thread, one of the resulting threads (an
implementation can choose to always select the same one, or to
randomize, or use any other means of selection as long as it always
chooses exactly one; I hope to cause this to say 'a random thread' in
the future, to make programming with woven threads more interesting,
but I haven't figured out how to implement that yet) counts as the
'original' thread and remains woven; the rest are 'new' threads which
initially start out with the same data as the original, but are not
woven with anything. Backtracking in a thread causes it to unweave
with any threads it may be woven with at the time (so the data in the
thread that backtracks is set back to the data it, and the threads it
was woven with at the time, had at the time of the MAYBE, but the
other threads continue with the same data as before). The only way to
cause three or more threads to become woven is with a new WHILE inside
one of the threads that is already woven, which causes all the new
threads to be woven together (the weaving relationship is transitive).

I think that rather lengthy description (written from memory, so I may
be wrong either due to faulty memory or due to misunderstanding the
behaviour of the code I wrote) covers all the possibilities I've
thought of so far. Something like DO RESUME #1 WHILE FINISH LECTURE is
pretty simple by comparison! (All that does is do both possible types
of return as new woven threads; because the right-hand side cannot
return, it means the whole confusion about when WHILE loops is
rendered moot, so this command is purely creating two woven threads
(one with a shorter NEXT stack and one with a shorter LECTURE stack),
and not doing anything else.)

--
ais523

0 new messages