Systems - NedoLang: The curse of the C language (part 3).

Info Guide #12
The Curse of the C Language
Alone Coder

   C is a terrible language. For all virtuals─
Chinese canons. But huge and unprecedented─ 
great support for its syntax in every utu─ 
ge in the absence of the same support from lu─ 
God of his competitors dooms development─ 
chicks of new languages copy and copy 
this syntax. 
   C problems (here and about C++), in two
words, boil down to the fact that it is complex in 
syntactic parsing and is fraught with 
mistakes. 

   The grammar is structured in such a way that it requires
know the right context: 
  - even if the parser knows all types
identifiers, he is still forced
look to the right at the width of the bracket, because
that the left side of the assignment resolves
use parentheses.
  - even if we remember the context of the beginning
brackets, already in the lexer parsing expressions by─
requires looking two characters ahead -
This is how two-character operations work and
comments. (NedoLang only looks at
one character, so it does not have++/-- in
expressions, and comments are prohibited in some─
some places, for example, before[ in the array.)
 - we will not know that the function declaration
does not have a body (that is, that there is no need to separate─
allocate memory for the listed parameters),
until we read the announcementuntil the end.
   Plus a bunch of reserved words (after all
they can occur in the identification position─
kator) and many cases indefinitely─
th behavior.

   Errors due to non-obviousness:
  - ternary operator. He has a low price
priority, but they constantly forget to conclude it
in brackets.
  - the same with comparison operators. Moreover
they kindly returnint so you can
mess up, but the compiler won't tell you anything
said. There were no types in Xi's ancestor. But in
the first NedoLang also did not have types, but
no lessbool is there.
 - we know that in a good language the behavior
should not depend on declaration order
("The Design and Evolution of C++", p. 265).  However
same behavior if with logical operations
&& and|| depends on the order of the operands (ana─ 
logical AND THEN / OR ELSE in Ada language,
which are not operations, but part
commandsIF ). By the way, that’s why we don’t recommend them─
need to be overloaded, because this
maintenance cannot be repeated with your own code(Sat─
ter, Alexandrescu"Programming standards─
vania in C++", #30).
 - assignment in expression - it is on the right─
Ktika is not required, but constantly meets─
where they meant== . Some of the
they even write for this==.
 -int and unsigned int are implicitly cast
to each other, and not only them. Lots of surprises─
reeses, for example, when processing sound.
  - you write:
unsigned char c1, c2, c3;
void f(void)
{
 if (c1 == c2 + c3)
 c1=3;
}
 and think that calculations are done in bytes─
in the range? You miscalculated!(Derek M.
Jones. The New C Standard: An Economic and
Cultural Commentary - further cbook1_0b.pdf,
p. 206) - you don’t know how your
pointer until you scroll the source to
its definitions. Moreover, you don't even
you know where he will move if you come to him
add 1.
  - you don’t know the symbolicitychar(Ostrich─
corpse "C++ Programming Language", p. 51).
By the way, I should have guessed to call it that
byte type. The authors probably didn't think
that there are languages other than English.
  - type errorswhile();{}
 - type errorsif();{}
 - type errorsif()if(){}else ...; -else
to the wrong branch.
  - type errorsfunc; instead of func(); - co─
compiles, but does nothing!
  - you write:
#include 
#include 
int main(void)
{
 printf("Startedn");
 if (fork() == 0)
 printf("Childn");
}
 and expect:
Started
Child
 But on some systems you may
wait for a surprise:
Started
Started
Child
 This is because the process can clone─
together with file buffers
(cbook1_0b.pdf, p. 202).
 - it’s tempting to write without parentheses:
#define A(x) x+1
 It might even work. Sometimes.
  -010 is not 10. (I did it so that
NedoAsm swore at this. Write octal─ 
constants in the form0o10 or do not write
in general!)

   Poor readability of the source:
  -int *a, b - how many pointers are there?
 -*a++ - is it *(a++) or (*a)++?
 -for (i=0; i<5; ++i){} - when happens─
dit++i ?
 -((void(*)(void))0)(); - this is a challenge about─
procedures with address 0. You can repeat, do not
peeking? Even fkO couldn't, I missed it
bracket.  I recommended the website cdecl, which
translates from English to C gibberish and image─
exactly, for example:
 int (*(*foo)(void ))[3]
declare foo as pointer to function (void)
returning pointer to array 3 of int
 - an equally designed typecast can
mean as a reinterpretation of meaning in
register, and its narrowing-expansion, or
even conversion to/from format(s) with pla─
important point, also with an unpredictable ok─
swearing! But there is no truncation by range.
Not in any way. Fixed point too
no.
  - can’t find function declaration pro─
thy search ("Design and evolution of C++", p.
316), all type conversions are also not found
(ibid., p. 334).
 - We write:
#define a b (possibly inside #include)#include ..
 and the macro will operate in a nested
library that there is a surprise for her("Di─
sign and evolution of C++", p. 429). But nao─
the rotation is quite necessary: we include macros, distance─
Now we work with macros.

 Other issues:
 -a >> n, a << n, p + n - not algebraic─
skiy operations, because their operands are different
type.
  - subtraction of pointers, comparisons - not
algebraic operations, because their result
another type.
  - lines without length - a wonderful hole
in the system. And they are also a very “fast” horse-drawn horse─
shadowing.
  - the language devilishly encourages reading
structures from a file and write them to the file. Yes─
also offers typeshort int for 16-bit
values and union for multi-valued fields.
DO NOT DO THIS. It's not portable.
  - etc., see type standardsMISRA C (I
I even collected a whole collection of such standards─
Comrade) and a book fromPVS-Studio"The Ultimate
Question of Programming" (aka"Main 
question of programming, refactoring and
all that" ).

   What else is missing:
  - support for different types of memory in the computer─
types (ROM, built-in RAM, external RAM;
in the case of Z80 it is also bankable/non-bankable─
May). Bypassed in some compilers,
for example, throughconst (other pointers
checked when attempting to access) or through
far.
 - moreover, we don’t even know which
the memory area that interests us will fall
label For example, the initialization section may
to be or not to be, even in different versions
the same SDCC.
  - runtime range check, which is in
Pascale.
  - nested comments. It is assumed
write#ifdef, whose body cannot be highlighted─
is available in editors. Find what you missed
#endif in a file is very fun entertainment─
nie.
  - export of tags. Bypass viastatic
(I export the rest of the labels by default─
tsya - poor linker).
  - non-addressable arrayspointers.
Slowly such banked arrays
megabytes in size. The problem is that
in C, an array and a pointer are one and the same
same. It doesn't work. If you write graphically─
cool editor, you'll have to break it yourself
your picture to many bankable
objects.
  - length of string literals.  You can't
generate a string literal with length.
You can only calculate the length separately
viaconstexpr in C++11 :https://
stackoverflow.com/questions/25890784/
computing-length-of-a-c-string-at-compile-
time-is-this-really-a-constexpr
 - Sishnik does not allow you to generate mass─
siv with symbolic names and indices
procedures (with addresses you can:https://
gcc.gnu.org/onlinedocs/cpp/
Concatenation.html ), because there is no time─
torn enum and torn initialization
constant array. For comparison, in ALASM
all this is possible.
   For the same reason there is no possibility, not
describing twice, generate an arrayindexes for string constants, using─
stored in the program (for a task like stored─
data available by name).
  - the function does not return a result and errors─
bku (which we saw in the iS-DOS functions, in
language Go and wait in C++17 called
"structured bindings") As a result, the usual
but some values are reserved for error─
ku.Especially chic-1 in getc(), for which
the function returns int instead of a byte - but
you understand, the guys still put inchar and
cut off the file in encodingCP1251 by letter
"I". And in C++ exceptions appear for every ─
fucking sneeze, of which you must─
you will definitely forget to process (especially if
it came running to you from the library). Spe─
exceptions are not checked statistically─
cheski(Sutter, Alexandrescu, #75).  By the way─
ty, division by0 may in some systems
give an exception even for floats, carried─
depending on the presence of infinities and NaN
(cbook1_0b.pdf,p.267). Moreover, except─
ion may not occur during division itself,
and, for example, when comparing(ibid., p.343).
And exceptions are also passed by value, but
must be caught by reference (otherwise
the derived class is truncated by the base one,
which we catch - seeMisra C++ 2008 Rule
15-3-5 ).
 - no tracking of pure functions (which
some do not depend on the environment and do not change
him). But according to the mind in expressions you can
use only them.
  - there is no operation of transferring an object with a name
copying the original (pass the pointer,
call a function, destroy the pointer).
With a functional programming style
in most cases destruction of objects
only needed here, and would not be necessary
remember whether we destroyed the original volume─
ect (in a number of other languages there is
garbage collector).
  - it is impossible to make a general else for
condition groups. (Although this is even in kva─
Dratno-nesting language DRAGON.)
  - inmain() the system environment is not transmitted─
tion (PATH, etc.), it has to be read
via a global variableextern char **
environ(cbook1_0b.pdf,p.168). Moreover,
no object(s) are passed to main()
system states (paths, console, settings
launch mode, FS, task descriptor...).
All this also has to be obtained through
one place, with support for retrieving
through this place is needed at the OS level. And you don't
you can mock these objects when on─
writing tests.
  - in standard C (at least C90) and in
The C++ standard does not define the concept of code─
new source and runtime environment tables
(cbook1_0b.pdf, p. 213). As a result, on Wednesday
execution gets exactly what you write─
put it in quotes, without any recoding─
nia. You will have a hard time writing on Linux
programs for ZX Spectrum encoded
CP866.

   And this evil had to be realized.

   I decided to compromise - leave
at least strong typing and optional─ 
ity;at the end of the line, disable arithm─ 
tick for typechar,aifandwhileprotect 
obligatory curly brace and dotcomma. 

 12/19/2016 - written as a separate project
work with dynamic memory, which
I was supposed to use it in the bootloader OP─
rational system.

 12/20/2016 - conducted an experiment with dyna─
mic memory. 85% filling. Not degra─
directs.

 01/10/2017 - made a typecast via
+() . Before this there was only type─
cast toint through prefix +, to unsigned─
new types through binary& , and in long - what
res0L+ .

01/11/2017 - I suddenly realized that I was awesome─
ksnye ++/-- cannot be implemented without obligation─
solid semicolons at the end of the command,
Or you will have to count the number of spaces.
I wrote it down in a memo.

 01/17/2017 - in calls instead of type in
/*...*/ made a typecast, and the name of the pair─
meters are not written (for this you had to create
barkseparate string stack):
 LET _barr[.vas]=
 +(byte)byter(
 recursive(byte)+(byte)shmyter2(
 recursive (byte)0b1
 )
 )
 This is not a stack or register transfer
giving parameters. Where to write the parameter when
call, determined by the parameter number.
A pair number is attached to the function name─
meters. And inside the function the same cell is
uses by name. That is, one and the same
the same cells have two labels.

 01/18/2017 - started translating the source code
compiler for the NedoLang language. To begin with
placed PROC, FUNC and +(BOOL)Oxff/0x00
instead oftrue/false .

 01/19/2017 - placed in the source code com─
pilator VAR (and removed the commas because
PINT a,b -this is int *a,b , and what does this mean? 
you already read above),LET,REPEAT...UNTIL,
and the module syscalls was completely translated into
NedoLang. 

 01/20/2017 - another insight:
 - you can make a call without call, if
check bracket( after the command - but then─
yes, names with a dot are not allowed.
  - you can make an assignment (not mass─
vov) withoutlet, if you check = after the coma─
nds - but then names with a dot are not allowed.
  - you can do array assignments
without let, if you check [ after the command -
but then names with a dot are not allowed.

 01/23/2017 - approximately translated the module
reader on NedoLang. To do this, I added op─
determination of a constant (commandconst).
but prohibited pointer arithmetic from naru─
typing change, andtrue and false allowed
write as+true , +false .

 01/24/2017 - roughly translated into Nedo─
Lang is the main part of the compiler. 

 01/27/2017 - the idea came to make + pre─
fix for all constants, and at the same time for sub─
fairy tales to the compiler typeregfast . But not
did.

 02/08/2017 - separated the GUI into a separate one
project.

 02/09/2017 - completed forward for the process─
dur/functions.

 02/10/2017:
 - removed manual indication of function types and
parameters when called. This information is not
is taken from the labels table.
  - the recursiveness of the function is stored in a tab─
face marks and is marked with the wordRECURSIVE
after its name in the definition.
  - global variables now starting─
with__ , and with one _ we only get
one level higher.

 02/13/2017 - ideas on pointers for pro─
procedures and functions. But he didn't. Experiment─
ntered with sequential dos files─
stupid in TR-DOS (before this the only time I
I tried them probably in 1995).

 02/14/2017:
 - constant arrays have been added (not for
lines,because for strings you need to generate
place separate marks). But I admit the lines─
is expressed in ordinary constants.
  - unpopular measure: difference indicate─
lei givesint.

 02/16/2017:
 - removedLET, CALL and THEN.
 - figured out in general terms how to do
far pointers. But not far calls. And not sde─
lal. We need to put the project through another process─
how many bottlenecks before dissolving?
expand.

 02/17/2017:
 - addedEXTERN for external variables.
 - removed ENDIF. Instead, protect from
error will be a trailing semicolon.

 02/20/2017 - removed some warnings
from gcc, which were sent byLVD.

 02/21/2017 - bugfix of the label table in
assembler.

 02/22/2017 - developed a design style
source and brought all the modules to it.

 02/23/2017 - each module is already from─
is compiled (withoutassembled─
nia).

 02/25/2017 - I was able to compile the ac─
assemble the main part of the compiler.
I wrote a .bat script for this. First time
it turned out 60491 bytes. Tweaked it a little
turned out58515 bytes.

Share your thoughts about the article