Author Topic: [SOLVED] Oxygen's Equivalents to C, Pls?  (Read 12375 times)

0 Members and 2 Guests are viewing this topic.

Mike Lobanovsky

  • Guest
[SOLVED] Oxygen's Equivalents to C, Pls?
« on: October 03, 2014, 06:58:00 PM »
Hi Charles,

1. Is there any way to express the following two C macros in Oxygen?

#define num_ivalue(p)      (isfixnum(p) ? (p)->_object._number._value._ivalue : (__i64)((p)->_object._number._value._rvalue))
#define num_rvalue(p)     (isflonum(p) ? (p)->_object._number._value._rvalue : (double)((p)->_object._number._value._ivalue))


Or do I have to recode all occurences to explicit nested If/Then/Else's because the macros can be both lvalues and rvalues of the same C expression, e.g.

if (num_ivalue(a) >= num_ivalue(b))
    do_this();
else
    do_that();



2. Can I have an Oxygen array of user-defined function pointers and call them efficiently based on their array indices or do I have to turn everything into one huge goto jump table instead to speed things up? The functions are void voids, i.e. arg-less subs in BASIC terms.


Thanks!
« Last Edit: October 03, 2014, 10:29:49 PM by Mike Lobanovsky »

Mike Lobanovsky

  • Guest
More Oxygen's Equivalents, Pls
« Reply #1 on: October 03, 2014, 08:04:43 PM »
While we are at it, some more questions:

1. Does the PP understand C-style semicolons if I leave them in place? And also in structs and typedefs?

2. Does O2 need some switch to understand C notation in its PP and elsewhere similar to your #basic or #o2h?

3. Where should I put C-style names for structs and unions in typedef and struct declarations -- before the opening brace or after the closing one? What if I have the same name both before the opening brace and after the closing one?

4. Do Oxygen's user-defined functions fetch their returns in eax and on the FPU stack after inline asm calls to their function pointers in other O2 user-defined functions? Are all O2 functions STDCALL on default?


Thanks again!

Charles Pegge

  • Guest
Re: Oxygen's Equivalents to C, Pls?
« Reply #2 on: October 03, 2014, 08:32:22 PM »
Hi Mike, I hope this answers your first set of questions. I did not quite understand those C macros.

Code: [Select]

'SET OF FUNCTIONS
=================

function funA(float f) as string, label
return "called funA: " & f
end function


function funB(float f) as string, label
return "called funB: " & f
end function

'BUILD TABLE OF FUNCTIONS
=========================

sys ftable={&funA,&funB}


'BOOLEAN COMPARATORS INDEXING A FUNCTION
========================================

indexbase 0

float b=1,c=1.1

sys a

a = (b<=c) 'result -1

a=(b<=c) and 1 'result 1

print cast (string) call ftable[a] (1234.5)

a = (b>=c) and 1 'result 0

print cast (string) call ftable[a] (1234.5)


'COMBINED:
==========

print cast (string) call ftable[ (b<=c) and 1 ] (1234.5)

« Last Edit: October 03, 2014, 09:25:54 PM by Charles Pegge »

Charles Pegge

  • Guest
Re: Oxygen's Equivalents to C, Pls?
« Reply #3 on: October 03, 2014, 09:11:04 PM »
1. Does the PP understand C-style semicolons if I leave them in place? And also in structs and typedefs?

By fefault, semicolons are treated as comment markers, so they can be left in most of the time.

However: iterators require the switch:


#semicolon separator

for (i=0 ; i<3 ; i++)  {print i} 'o2 now understands




2. Does O2 need some switch to understand C notation in its PP and elsewhere similar to your #basic or #o2h?

There isn't a C switch. but case sensitivity is often important:

#case sensitive

a good compromise is:

#case capital 'sensitive to fully capitalised symbols

O2 understands C notation with some exceptions:

conditional choice expressions:  (? ...)

-> arrow notation (o2 pointers are implicit from the type definition)

pointer expressions (implicit pointers)

Line sensitivity : beware split lines in C

Take nothing for granted! :)

3. Where should I put C-style names for structs and unions in typedef and struct declarations -- before the opening brace or after the closing one? What if I have the same name both before the opening brace and after the closing one?

typedef struct _Mytype
{
  int a,b
  union {
  long c
  double d
  }
} Mytype, *pMytype



4. Do Oxygen's user-defined functions fetch their returns in eax and on the FPU stack after inline asm calls to their function pointers in other O2 user-defined functions? Are all O2 functions STDCALL on default?


Yes, STDcall for 32 bit code, but cdecl also available:

int f cdecl (int a)
{
 return 2*a
}



« Last Edit: October 03, 2014, 09:20:00 PM by Charles Pegge »

Mike Lobanovsky

  • Guest
Re: Oxygen's Equivalents to C, Pls?
« Reply #4 on: October 03, 2014, 09:32:50 PM »
(that's in response to your first answer)

Thanks Charles,

Your code answers my question number 2 from the starter message in full.

Other questions from the two messages yet remain unanswered. OK let's start one question at a time:

Code: [Select]
  /* cell structure */
  struct cell{
    unsigned long _flag;
    union {
      struct {
        char* _svalue;
        long  _keynum;
      } _string;
      struct {
        union {
          __int64 _ivalue;
          double  _rvalue;
        } _value;
      } _number;
      struct {
        struct cell* _car;
        struct cell* _cdr;
      } _cons;
    } _object;
  } cell;

  typedef struct cell* pointer;

  #define type(p)           ((p)->_flag)

  #define isfixnum(p)       ((type(p) & T_FLONUM) == T_NUMBER)
  #define isflonum(p)       ((type(p) & T_FLONUM) == T_FLONUM)

  #define ivalue(p)         ((p)->_object._number._value._ivalue)
  #define rvalue(p)         ((p)->_object._number._value._rvalue)

  #define num_ivalue(p)     (isfixnum(p) ? ivalue(p) : (__int64)rvalue(p))
  #define num_rvalue(p)     (isflonum(p) ? rvalue(p) : (double)ivalue(p))

where the argument (p) is of typedef pointer.

In other words, the ternary evaluation of isfixnum(p) or isflonum(p) -- the _flag field of structure cell -- in the last two macros at runtime will put one of the four:

1/2. either the _ivalue field or (__int64)_rvalue field of structure cell; or
3/4. either the _rvalue field or (double)_ivalue field of structure cell

into an expression of the following kind:

if (num_ivalue(a) >= num_ivalue(b))
    do_this();
else
    do_that();



So, my question is: can Oxygen use these C macros as they are defined above to perform the required substitutions in the above code piece as efficiently, or do I have to abandon these macros altogether and re-write the occurences of num_ivalue(a) >= num_ivalue(b)-style expressions as explicit multiply nested BASIC If/Then/Else blocks (which would be some piece of work, I must admit)?
« Last Edit: October 03, 2014, 09:44:26 PM by Mike Lobanovsky »

Mike Lobanovsky

  • Guest
Re: Oxygen's Equivalents to C, Pls?
« Reply #5 on: October 03, 2014, 09:41:01 PM »
Thanks a lot for the second answer too, but still:

4. Do Oxygen's user-defined functions fetch their returns in eax and on the FPU stack immediately after inline asm calls to their function pointers in other O2 user-defined functions?
« Last Edit: October 03, 2014, 09:57:44 PM by Mike Lobanovsky »

Charles Pegge

  • Guest
Re: Oxygen's Equivalents to C, Pls?
« Reply #6 on: October 03, 2014, 10:05:07 PM »

Mike, I'm falling asleep. It is dawn and I must make haste to my casket. I'll attempt some answers later. But can you show me how those macros are deployed, by way of example pls?

Mike Lobanovsky

  • Guest
Re: [SOLVED] Oxygen's Equivalents to C, Pls?
« Reply #7 on: October 03, 2014, 10:27:42 PM »
Charles,

The above "if (... >= ...) ... else ..." is an example of actual deployment of these macros throughout the code. Never mind though: if you don't grasp their role in the C code at a first glance, it's most probably an indication that O2 wouldn't be able to mimic this functionality one to one anyway either.

I'll just take my time to rewrite the same with explicit If's.

Have a good night's (actually day's) sleep and thanks again for your help! :)

Charles Pegge

  • Guest
Re: [SOLVED] Oxygen's Equivalents to C, Pls?
« Reply #8 on: October 04, 2014, 01:22:20 AM »
Mike,

Conditional Possibilities:

functions are required if you want to use the conditional inside an expression

Code: [Select]
float aa=1,bb=2,cc=3,dd=4,ee=5

#define conddo(a,b,c) if a then b else c

conddo aa>bb, cc=dd, cc=ee
print cc

float  iff(sys a, float  b,c)    { if a {return b} else {return c} }
sys    iff(sys a, sys    b,c)    { if a {return b} else {return c} }
string iff(sys a, string b,c)    { if a {return b} else {return c} }


aa=iff ((bb<=cc),dd,ee)
print aa

« Last Edit: October 04, 2014, 05:33:06 AM by Charles Pegge »

Charles Pegge

  • Guest
Re: [SOLVED] Oxygen's Equivalents to C, Pls?
« Reply #9 on: October 04, 2014, 01:33:01 AM »
4. Do Oxygen's user-defined functions fetch their returns in eax and on the FPU stack immediately after inline asm calls to their function pointers in other O2 user-defined functions?

Yes, if you make a call to a function returning a float or a double, then the result will be left on the FPU stack.

In 32 bit mode, quad integers are also returned on the fpu stack

Otherwise, the value will be in the eax register (eax and edx are preserved during epilog operations)

If the function being called uses cdecl then you must restore the stack pointer to its prior position. However, if the function is called in basic syntax: call fun a,b,c,d then the stack pointer adjustment will be automatic.

« Last Edit: October 04, 2014, 01:54:24 AM by Charles Pegge »

Mike Lobanovsky

  • Guest
Re: [SOLVED] Oxygen's Equivalents to C, Pls?
« Reply #10 on: October 04, 2014, 07:46:51 AM »
Quote
Conditional Possibilities:

Oh yes, FBSL (following VB6) does have a built-in ternary function that would return a simple value choice, which does the same as what you suggest:

d = IIf(a, b, c)    (your functions are called iff)

or

If IIf(a, b, c) >= IIf(d, e, f) Then

but this would imply an overhead of two extra function calls in one expression of the if (a <> b) then kind. The comparisons are parts of nanoscheme's jump table and implement its arithmetic comparison procedures <, <=, >=, >. (Arithmetic equality/inequality is expressed via (equal?)/(not (equal?)).)

Therefore I was trying to avoid additional function calls here altogether, and those elegant C macros helped me do just that. Anyway, I'll try to use the functions as you suggest and see if they have significant impact on my benchmarks. If yes then I'll re-write them as explicit If/Then/Else blocks.

Your eax/FPU answer is exhaustive for my purposes. Thanks a lot again for your invaluable help! :)

Charles Pegge

  • Guest
Re: [SOLVED] Oxygen's Equivalents to C, Pls?
« Reply #11 on: October 04, 2014, 08:43:05 AM »
Hi Mike,

If most of your conditional return values are floats/doubles then this float macro should be very efficient. It will work for integers too:

iff ( comparator_expr,  true_return_expr, false_return_expr )

Code: [Select]
deff iff
or eax,eax
(
jnz exit
fxch st1
)
fstp st0
end deff



'TEST:

sys aa=1,bb=2,cc=3,dd=4,ee
ee = iff((aa>bb),cc,dd)
print ee '4

float aa=1,bb=2,cc=3,dd=4,ee
ee = iff((aa<bb),cc,dd)
print ee '3

So I suggest using a macro like this one, wherever it fits your coding pattern. It can be adjusted later, if necessary. Macros and functions both use the same syntax when you call them.
« Last Edit: October 04, 2014, 09:08:26 AM by Charles Pegge »

Mike Lobanovsky

  • Guest
Re: [SOLVED] Oxygen's Equivalents to C, Pls?
« Reply #12 on: October 04, 2014, 10:46:23 AM »
Hi Charles,

Values to compare will always be either doubles or quads. There are no more 32-bit integers in nanoscheme.

Will the macro be as efficient for quads? (I think it should since your quads are essentially flints, i.e. 64-bit floats with zero fractional part...)

Charles Pegge

  • Guest
Re: [SOLVED] Oxygen's Equivalents to C, Pls?
« Reply #13 on: October 04, 2014, 11:08:59 AM »
Quads, as 64 bit signed integers,  are handled by the FPU when compiled in 32bit mode.

But when RTL64.inc is included, quads are handled directly by the cpu for expression evaluation. However quad variables are loaded directly into the FPU during float macro operations, or when the assignment variable is a float.


I will shortly be tweaking the assembler to facilitate dual 32/64 bit coding. When in 32bit mode, Registers rax..rdi will be automatically down graded to eax..edi

Thus the iff macro should be expressed (with the new compiler) like this:

deff iff
or rax,rax
(
jnz exit
fxch st1
)
fstp st0
end deff
« Last Edit: October 04, 2014, 11:17:52 AM by Charles Pegge »

Mike Lobanovsky

  • Guest
Re: [SOLVED] Oxygen's Equivalents to C, Pls?
« Reply #14 on: October 04, 2014, 11:19:54 AM »
Then I'll emit nanoscheme as a 32-bit application with 64-bit calc and then you'll port it to RTL64.inc yourself. It will then be the best, beautifullest, and fastest Scheme interpreter on the net, guaranteed. :D