Greatest of three numbers

  • Thread starter Amar Kumar Dubedy
  • Start date
C

cr88192

Harald van D?k said:
<OT, I guess>
You're right, this isn't the best group for that, but you might like the
comp.compilers newsgroup for it.
</OT>

sadly, it is moderated and filled with people obsessing on parsers...

as a result, had mostly been hanging around alt.lang.asm and comp.lang.misc.

here seems to be mostly a place for newbs to ask questions...


OT, basic description of effort:

now, my parser, well, it is a big mass of hand-written C code, not much to
say about that (I suspect most people with any interest in compiler or
interpreter writing, maybe run into the problem of syntax, or get some crude
interpreter or translator working, and die off after this point).

parser is uniteresting, hard-coded recusive-descent...

now, IMO, the parser is the easy part...


the compilation process, type handling, and code generation. IMO, this is
where most of the work seems to reside (note, I compile all the way down to
machine code using purely my own code).

currently the thing is about 30 kloc, but a lot is still incomplete.

note that it is a multi-stage compiler (currently 5 major stages, with some
of these stages making multiple passes).


I am aiming for calling-convention level compatibility with gcc.

in general, it is designed for run-time compilation and linking (so that it
can operate similarly to a script language), but also have full (and direct)
access to the OS and host app.

at present it can also load object files and static libraries (GNU-ar
format), and can output object files, albeit for all these presently only
PE/COFF is supported (what little I have run it on linux, it is restricted
to what can be done with libdl).

another eventual goal is to allow its use for tasks along the lines of
'eval' (dynamically compiling and running small pieces of code, such as
single expressions), self-writing programs, ...


other possible eventual features:
reflection, ...
compiler extensions for high-level features (garbage collection, dynamic
types, lexical varaibles, closures, ...).

as noted, given a C core these would be less nice than in a true script
language (and totally craping all over the purity of C), but it could still
be worthwhile (well, probably still far less horrid than Objective-C, more
like what would happen if C, JavaScript, Self, ... collided, and more
keeping in line with the basic style and aesthetic of the C family...).

as is usual, probably requiring a special header, 'variant.h', which would
enable all this bizareness (and probably "#error" if used in something like
gcc...).


note:
this is really only my first statically-typed language, me previously
writing dynamically typed script languages (the final of which using JIT and
type inference, I had figured maybe it wouldn't be too huge of a leap from
one to another, but have been regularly underestimating things).

well, it was less easy than could be hoped, good 4+ solid months of coding
getting this beast written, internally, a very different thing than the
script language...

however, the framework should be able to handle both styles absent too much
additional effort (far less than writing the damn thing).


or something...
 
R

Richard Heathfield

cr88192 said:
yes, but note, I said, 3 integers > 0.

Note that your "solution" thus solved a different problem to the one
actually asked.
oh well, the main reason I was here was seing if this was a good place
to talk about compiler writing and design (namely, I wrote a C
compiler),

Presumably you were asked to write a Fortran compiler, and wrote at the
top of the design spec "assuming Fortran means C..."
 
R

Richard Heathfield

cr88192 said:

here seems to be mostly a place for newbs to ask questions...

Mostly, alas, that is true. In fact, the quality of the answers usually
far exceeds the quality of the questions.
OT, basic description of effort:

now, my parser, well, it is a big mass of hand-written C code, not
much to say about that (I suspect most people with any interest in
compiler or interpreter writing, maybe run into the problem of syntax,
or get some crude interpreter or translator working, and die off after
this point).

parser is uniteresting, hard-coded recusive-descent...

now, IMO, the parser is the easy part...

Well, the lexer is the easy part, actually. The parser is a bit harder
than the lexer.

<project description snipped>

Sounds like you're having lots of fun.
 
C

Chris Dollin

cr88192 said:
sadly, it is moderated and filled with people obsessing on parsers...

Topics move around. If you want c.c to talk about something else,
/post/ about something else.
 
C

cr88192

Richard Heathfield said:
cr88192 said:



Mostly, alas, that is true. In fact, the quality of the answers usually
far exceeds the quality of the questions.

yeah, sad really...

Well, the lexer is the easy part, actually. The parser is a bit harder
than the lexer.

true, but usually the lexer is easy enough, and done in the same pass as the
parser. as a result, I don't usually distinguish them.

so, what is the lexer?
maybe a few hundred loc?...
(source file, 514 loc, 130 going to line-number handling, 95 whitespace and
comments, 290 tokenizer).

parser? about 3 kloc total...

preprocessor, 741 loc;
expressions, 764 loc;
statements, 429 loc;
misc (definitions, args lists, ...), 733 loc.

very little actual "mechanics" are implemented by the parser (beyond
generating the ASTs).

the compiler is split into several stages:
upper (still needs a lot of work), 2.4 kloc, converts ASTs to a kind of IL
(I call RPNIL or RIL);
lower, 6.5 kloc (converts RPNIL to assembler, rather horrible code);
assembler, 10.25 kloc (obvious enough what this does...).


so, yeah, technically it is fairly small, but a lot of this code can be a
lot of effort to write and debug...

<project description snipped>

Sounds like you're having lots of fun.

if I am lucky it could actually be useful...
 
C

cr88192

Richard Heathfield said:
cr88192 said:


Note that your "solution" thus solved a different problem to the one
actually asked.

ok.

yes, 'number' and 'counting-number' are not necissarily the same.

Presumably you were asked to write a Fortran compiler, and wrote at the
top of the design spec "assuming Fortran means C..."

hmm...

actually, this project was done for my own reasons:
it could be useful for my larger-scale project...

but, it has consumed more time and effort than I had originally expected (I
suspect my frequent depressive runs slow me down...).
 
C

Christopher Benson-Manica

Richard Heathfield said:
Note that your "solution" thus solved a different problem to the one
actually asked.

Given that the question actually asked was homework, maybe that was a
good thing...
 
D

David Resnick

How to find the greatest of three numbers without using any comparison
operator or ternary operator??

This is probably not what your professor wants (which is why I'm
willing to show it), but assuming c99 is available and that every
integer can be exactly represented as long double it seems to work:

#include <stdio.h>
#include <math.h>

int max(int a, int b, int c)
{
return fmaxl(fmaxl(a,b),c);
}

int main(void) {
int a= 5;
int b= 10;
int c= -3;

printf("%d\n", max(a,b,c));
return 0;
}

Is it in theory possible that a long double can't exactly represent
the largest possible integer and this will fail? If so, I'm sure
someone will say so. I don't use floats much, and lost interest
deciding whether DECIMAL_DIG or any of the other set of defines in
float.h is relevant here.


-David
 
K

Keith Thompson

Richard Heathfield said:
cr88192 said:


Mostly, alas, that is true. In fact, the quality of the answers usually
far exceeds the quality of the questions.
[...]

Well, the opposite would be worse.
 
R

regis

#define N (CHAR_BIT * sizeof (unsigned) - 1)

int /* returns the carry flag of the sum a+b */
carry_flag (unsigned a, unsigned b)
{
int cf [2][2][2]= {{{0,0},{1,0}},{{1,0},{1,1}}};
unsigned s= a + b;
return cf [a >> N] [b >> N] [s >> N];
}
>
int /* returns 1 iff a < b */
below (unsigned a, unsigned b)
{
return carry_flag (a + ~b, 1)
| carry_flag (a , ~b)

}

Hmm, the function below() shown above is in fact above_or_equal().
The function shown below is indeed below() with a clearer logic:

int carry_flag (unsigned a, unsigned b, unsigned carry_in)
{
int cf [2][2][2]= {{{0,0},{1,0}},{{1,0},{1,1}}};
unsigned s= a + b + carry_in;
return cf [a >> N] [b >> N] [s >> N];
}

int below (unsigned a, unsigned b)
{
return 1 - carry_flag (a, ~ b, 1);
}
 
P

Peter Nilsson

regis said:
if all three are unsigned...

#define N (CHAR_BIT * sizeof (unsigned) - 1)

The expression is flawed since unsigned ints can have
padding bits.
int /* returns the carry flag of the sum a+b */
carry_flag (unsigned a, unsigned b)
{
int cf [2][2][2]= {{{0,0},{1,0}},{{1,0},{1,1}}};
unsigned s= a + b;
return cf [a >> N] [b >> N] [s >> N];
}

return ( (a >> 1)
+ (b >> 1)
+ (((a & 1) + (b & 1)) >> 1) ) / (-1u/2+1);
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,130
Latest member
MitchellTe
Top