Deutsch   English   Français   Italiano  
<vbkpfc$27l2o$1@paganini.bofh.team>

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

Path: ...!weretis.net!feeder8.news.weretis.net!newsfeed.bofh.team!paganini.bofh.team!not-for-mail
From: Waldek Hebisch <antispam@fricas.org>
Newsgroups: comp.lang.c
Subject: Re: Top 10 most common hard skills listed on resumes...
Date: Sun, 8 Sep 2024 18:13:02 -0000 (UTC)
Organization: To protect and to server
Message-ID: <vbkpfc$27l2o$1@paganini.bofh.team>
References: <vab101$3er$1@reader1.panix.com>   <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> <vbhbbb$1blt4$1@dont-email.me> <vbipp5$24kl5$1@paganini.bofh.team> <vbk0d9$1tajm$1@dont-email.me>
Injection-Date: Sun, 8 Sep 2024 18:13:02 -0000 (UTC)
Injection-Info: paganini.bofh.team; logging-data="2348120"; posting-host="WwiNTD3IIceGeoS5hCc4+A.user.paganini.bofh.team"; mail-complaints-to="usenet@bofh.team"; posting-account="9dIQLXBM7WM9KzA+yjdR4A";
User-Agent: tin/2.6.2-20221225 ("Pittyvaich") (Linux/6.1.0-9-amd64 (x86_64))
X-Notice: Filtered by postfilter v. 0.9.3
Bytes: 19276
Lines: 431

Bart <bc@freeuk.com> wrote:
> On 08/09/2024 01:05, Waldek Hebisch wrote:
>> Bart <bc@freeuk.com> wrote:
> 
>>> 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.
>> 
>> First, it is not my goal to advocate for Forth use.
> 
> You're doing a fine job of it!
> 
> For me it's one of those languages, like Brainf*ck, which is trivial to 
> implement (I've done both), but next to impossible to code in.

I wonder if you really implemented Forth.  Did you implement immediate
words? POSTPONE?

> With Forth, I had to look for sample programs to try out, and discovered 
> that Forth was really a myriad different dialects. It's more of a DIY 
> language that you make up as you go along.

Well, there is the standard and several implementations that do not
follow the standard.  As in each language implementations have their
peculiar extentions.  And Forth is extensible, so there are user
extentions.
> 
>> : 2*3 =>
>> ** 6
>> : 2, 3, *() =>
>> ** 6
>> the first line is infix form, '=>' oprator prints what is on
>> the stack (but you cat treat it as "print current result").
>> In the second line two numbers are pushed on the stack and
>> then there is call to multiplication routine.  Parser knows
>> that '*' is an operator, but since there are no argument
>> '*' is treated as ordinary identifer and as result you
>> get multiplication routine.  Like in other languages parentheses
>> mean function call.  Up to now this may look just as some
>> weirdness with no purpose.  But there are advantages.  One
>> is that Pop11 functions can return multiple values, they just
>> put as many values as needed on the stack.  Second, one can
>> write functions which take variable number of arguments.
>> And one can use say a loop to put varible number of arguments
>> on the stack and then call a routine expecting variable
>> number of arguments.  In fact, there is common Pop11 idiom
>> to handle aggregas: 'explode' puts all members of the aggregate
>> on the stack.  There are also constructor function which build
>> aggregates from values on the stack.
> 
> This sounds like one of my bytecode languages.
> 
> So, in the same way that Lisp looks like the output of an AST dump, 
> these stack languages look like intermediate code:
> 
> 
>   HLL ->    AST     ->  Stack IL  ->  Interpret or -> ASM
>   (eg. C)   (Lisp)      (Forth)
>                         (Pop-11)

Well, in Pop11 it it more like

       reader           parser
   HLL   -> token stream -> Stack IL -> ASM or machine code in memory

Both reader (responsible for turning characters into tokens) and
parser are user extensible.  For example, general addition is defined
as:

define 5 x + y;
    lvars x, y;
    if isinteger(x) and isinteger(y) then
        if _padd_testovf(x, y) then return() else -> endif
    endif;
    Arith_2(x, y, OP_+)
enddefine;

The '5' after 'define' means that we are defining an operator which
have priority 5.  'lvars' says that 'x' and 'y' obey lexical
scoping (one could use 'vars' to get dynamic scope instead).
The 'isinteger' test check for machine-sized integers, if both
'x' aand 'y' are integers this takes fast path and uses machine
addition (with check for overfolw).  In case of no overflow the
result of machine addition is return.  Otherwise 'Arith_2' handles
(hairy) general cases.  Users can define their own operators.
For example

define 7 x foo y; y; enddefine;

defines operator 'foo' (of higher priority than addition).  And
we can use it:
: 1 foo 2 =>
** 2 
: 2 + 3 foo 4 =>
** 4 
: 2 + (3 foo 4) =>
** 6

Naive Fibonacci routine may look like this:

define fibr(n);
    if n < 2 then 1 else fibr(n - 1) + fibr(n - 2) endif
enddefine;

Note that use of the stack is invisible above, user may treat this
as something like Pascal, only that source language structures
must be terminated by verbose 'endif' and 'enddefine' respectively.
OTOH there is no need for explicit return, last value computed is
the return value.

There are some anomalies, assignment is written as:

a -> b;

which means assign a to b.  There is 'printf' which works
like this:

: printf(2, '%p\n');  
2
: printf(2, 3, '%p %p\n');
3 2

Note that order of printed values is reversed compared to source
and format comes last, this is due to stack semantics.  You
can write things like:

external declare tse in oldc;

void
tse1(da, ia, sa, dp, ip, sp, d, i, s)
    double da[];
    int ia[];
    float sa[];
    double * dp;
    int * ip;
    float * sp;
    double d;
    int i;
    float s;
{
}

endexternal;

The first line switches on syntax extention and lines after that
up to 'endexternal' are parsed as C code.  More procisely, 'oldc'
expects KR style function definitions (with empty body).  As
result this piece of code generates Pop11 wrapper that call
corresponding C routine passing it arguments of types specified
in C definition (but on Pop11 side 'double da[]' and 'double * dp'
are treated differently).  Note that this in _not_ a feature of
core Pop11 langrage.  Rather it is handled by library code (which
in principle could by written by ordinary user.

> Most people prefer to code in a HLL.

You mean "most people prefer by now traditional syntax", sure.

> But this at least shows Lisp as 
> being higher level than Forth, and it's a language that can also be 
> bootstrapped from a tiny implementation.

Pop11 has very similar semantics to Lisp and resonably traditional
syntax.  I would say that Lisp users value more extensibility than
traditional syntax.  Namely Lisp macros give powerful extensibility
and they work naturaly with prefix syntax.  In particular, to do
an extension you specify tree transformation, that is transformation
of Lisp "lists", which can be done conveniently in Lisp.  In Pop11
extentions usually involve some hooks into parser and one need to
think how parsing work.  And one needs to generate representation
at lower level.  So extending Pop11 usualy is more work than extending
Lisp.  I also use a language called Boot, you will not like it
because it uses whitespace to denote blocks.  Semantics of Boot is
essentially the same as Lisp and systax (expect for whitespace)
is Algol-like.  A sample is:

dbShowConsKinds(page, cAlist) ==
  cats := doms := paks := defs := nil
  for x in cAlist repeat 
    op := CAAR x
    kind := dbConstructorKind op 
    kind  = 'category => cats := [x,:cats]
    kind = 'domain    => doms := [x,:doms]
    kind = 'package   => paks := [x,:paks]
========== REMAINDER OF ARTICLE TRUNCATED ==========