Warning: mysqli::__construct(): (HY000/1203): User howardkn already has more than 'max_user_connections' active connections in D:\Inetpub\vhosts\howardknight.net\al.howardknight.net\includes\artfuncs.php on line 21
Failed to connect to MySQL: (1203) User howardkn already has more than 'max_user_connections' active connections
Warning: mysqli::query(): Couldn't fetch mysqli in D:\Inetpub\vhosts\howardknight.net\al.howardknight.net\index.php on line 66
Article <vbhbbb$1blt4$1@dont-email.me>
Deutsch   English   Français   Italiano  
<vbhbbb$1blt4$1@dont-email.me>

View for Bookmarking (what is this?)
Look up another Usenet article

Path: ...!news.mixmin.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: Bart <bc@freeuk.com>
Newsgroups: comp.lang.c
Subject: Re: Top 10 most common hard skills listed on resumes...
Date: Sat, 7 Sep 2024 11:53:32 +0100
Organization: A noiseless patient Spider
Lines: 176
Message-ID: <vbhbbb$1blt4$1@dont-email.me>
References: <vab101$3er$1@reader1.panix.com> <vanq4h$3iieb$1@dont-email.me>
 <875xrkxlgo.fsf@bsb.me.uk> <vapitn$3u1ub$1@dont-email.me>
 <87o75bwlp8.fsf@bsb.me.uk> <vaps06$3vg8l$1@dont-email.me>
 <871q27weeh.fsf@bsb.me.uk> <20240829083200.195@kylheku.com>
 <87v7zjuyd8.fsf@bsb.me.uk> <20240829084851.962@kylheku.com>
 <87mskvuxe9.fsf@bsb.me.uk> <vaq9tu$1te8$1@dont-email.me>
 <vbci8r$1c9e8$1@paganini.bofh.team> <vbcs65$eabn$1@dont-email.me>
 <vbekut$1kd24$1@paganini.bofh.team> <vbepcb$q6p2$1@dont-email.me>
 <vbgb5q$1ruv8$1@paganini.bofh.team>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Sat, 07 Sep 2024 12:53:32 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="0a8001fc0483eb71abd00b3625106a2f";
	logging-data="1431460"; mail-complaints-to="abuse@eternal-september.org";	posting-account="U2FsdGVkX1/uBB7cj1xDPCgZv2Th5uOx"
User-Agent: Mozilla Thunderbird
Cancel-Lock: sha1:ye7E2QrgUNRK0VfnRi60HPcRnGY=
Content-Language: en-GB
In-Reply-To: <vbgb5q$1ruv8$1@paganini.bofh.team>
Bytes: 7664

On 07/09/2024 02:44, Waldek Hebisch wrote:
> Bart <bc@freeuk.com> wrote:
>> On 06/09/2024 11:19, Waldek Hebisch wrote:
>>> Bart <bc@freeuk.com> wrote:

>> (You can balance it out by by requiring ASSIGN(&A, &B)!)
> 
> This would not work in general, as I wrote it, the following are
> valid:
> 
> assign(&a, 42)
> assign(&a, a + 1)
> 
> but the second argument has no address, so your variant would not
> work.

I believe that C's compound literals can give a reference to a+1:

   #include <stdio.h>

   void assign(int* lhs, int* rhs) {
       *lhs = *rhs;
   }

   int main(void) {
       int a=20;

       assign(&a, &(int){a+1});

       printf("a = %d\n", a);
   }


The output from this is 21.

(You are not supposed to ask questions about how assign() can be 
implemented if assignment statement is not available. Here I'm just 
showing the symmetry at call-site and in callee.)

> You can use stack machines to get reasonably simple definition of
> semantics.  But still slightly more complex than what I outlined
> above.  And code for stack machines is unpleasent to optimize.
> In a compiler for a language where official semantics is stack
> based the first things that compiler does is to track few items
> on top of the stack and match them to sequences like
> 
> push a
> push b
> call op
> 
> Once sequence is matched it is replaced by corresonding operation
> on variables.  If this matching works well you get conventional
> (non-stack) intermediate representaion and reasonably good code.
> If matching fails, the resulting object code wastes time on stack
> operations.

(My stack IL is different. The stack is a compile-time stack only, and 
code is scanned linearly during code-generation. Roughly, the 'stack' 
corresponds to the machine's register-file, although in practice 
register allocation is ad-hoc.

In my current scheme, the  hardware stack is rarely used except for 
function calls. You might notice I use Load/Store rather than Push/Pop, 
this was to avoid confusion with hardware push/pop instructions.

When A and B are in registers, then A=B results in a register-register 
move.)

> 
> Of course, if you don not minds slowdowns due to stack use, then
> stack machine leads to very simple implemantaion.

I use a software stack for interpreted code.

>  Best Forth compilers
> have sophisticated code to track stack use and replace it by
> use of registers.  Other Forth compilers just accept slowness.

Then you no longer have a language which can be implemented in a few KB. 
You might as well use a real with with proper data types, and not have 
the stack exposed in the language. Forth code can be very cryptic 
because of that.

My IL stack code is typically easier to follow than Forth, and would be 
easier to write, if still a slog. (That's why I use a HLL!)


>> Obviously, you can have RHS terms that cannot appear on the left, like
>> '42', but that's usually due to separate constraints of the language.
> 
> Well, logically you can not change value of a number, so you can
> not assign to a number, that is very fundamental.

But it's not prohibited by the grammar.

>  You could
> try to define
> 
> x + 1 = y
> 
> as solving equation for x, that quickly runs into trouble due to
> equations which are no solutions or multiple solutions.

(Actually, 'x + 1 = y' is well defined in my languages. But that's 
because '=' means equality. The result is true/false.)

>> Why don't you need to compute the address of B?
> 
> Well, B may have no address.  In case when B is variable computing
> its address is part of computation of its value.  In general,
> computing value of B need computing addresses of all variables
> contained in B.
> 
>> Why don't you need to
>> load the value of B?
> 
> "compute value" means putting result in place which is available
> to subsequent operations, so logically no extra load is needed.

If you look typical generated code, then 'compute value' can often 
require discrete loads. But sometimes it is implicit:

     add R, [b]

However, so is Store sometimes:

     add [a], R

> And for variables "compute value" includes loading them.
> 
>> It is more like this:
>>
>>    compute address of B
>>    load value of B via that address to some temporary location
>>    compute address of A
>>    store new value of A via that address
> 
> The point is that last part (that is store instruction) logically
> does not change when you vary A and B.  Only this part corresponds to
> assignment.  The first to lines logically form a whole, that
> is "compute B".  And when you vary B you may get quite different split
> of "compute B" into part.  Moreover, logically "compute value of B"
> and "compute address of A" are completely independent.

Suppose you had a 2-address machine with this instruction:

    mov [a], [b]                  # right-to-left

With a simple CPU, executing it might involve:

* Getting the address of b from the instruction into the address register
* Performing a memory read access to load b into a register
* Getting the address of a from the instruction into the address register
* Performing a memory write access to write the register to a

>>     (c ? a : b) = (c ? a : b);
> 
> As noticed, people prefer symmetric notation, so most languages
> make it "symmetric looking".  But if you dig deeper there is
> fundametal asymetry.

What started the subthread was the question of which HLL goes between 
ASM and C (since someone suggested that C was mid-level).

People suggested ones like BLISS and Forth.

I remarked that a proper HLL would let you write just A to either read 
the value of variable A, or write to it. Eg. A = A, without special 
operators to dereference A's address.

At the lower level it might be push/pop, load/store, or even *&A = *&A, 
========== REMAINDER OF ARTICLE TRUNCATED ==========