From: Maurizio Vitale (maurizio.vitale_at_[hidden])
Date: 2007-05-19 08:58:53


On May 19, 2007, at 12:02 AM, Gottlob Frege wrote:

> On 5/8/07, Maurizio Vitale <mav_at_cuma.polymath-solutions.lan> wrote:
>>
>> Suppose I needed a new tag for representing some high-level
>> concept that I do not want
>> to express in terms of C++ operators [it could be a get_bit(N)
>> operation that has very
>> different implementation when for my numbers the unserlyining
>> implementation is a
>> builtin type or a GMP big int]
>>
>> Here's my code for adding a binary operator my_plus:
>>
>
> For us new to proto, can you give an example of your DSEL in use where
> my_plus is used?
>
> ie is it:
>
> int a;
> int b;
>
> int c = ...my_plus....
>
> what's it look like in use?
>

Suppose you have objects that derives from proto::terminal, like
my_int in my previous posts.
Given the declarations:

        my_int<4> i=2;
        my_int<8> j=40;

You want to be able to write something like:
        i = my_plus(i,j);

Granted, you'd probably wouldn't do this for my_plus, as you have an
operator+ that looks nicer.
What I need the ability of defining new "functions" for is for things
like
sign(expr) - returns the sign of an expression
mask(expr, left, right) - return EXPR with bits outside the range
left..right zeroed.
etc.

The reason I want to represent those "high" [higher than C++
operations] concepts is that their implementation
is potentially very different. For instance extracting the sign from
a builtin type is not the same as extracting the sign from a fixed-
point number
and it is certainly not the same as extracting it from a GNU multi-
precision numbers.
Note that not necessarily a comparison w/ zero would do the right
thing: for instance in fixed point numbers
I might decide not to sign-extend after all operations
(which has a cost) and thus you have to fin the right inner bit that
gives you the sign.

In my application (a library of fixed-point numbers) I'll have two
levels where proto is used. A "concrete" level
that control the user-level expressions in the way one would expect
(similar to code I posted previously, like the example
that allows you to make all combinations containing signed numbers to
go to signed).

And then I have a meta-level where you can talk about expressions in
the concrete domain. For instance if
        proto::eval( i+j, concrete_context) gives you 42
I want:
        proto::eval(value(_2), meta_context(j, i+j)) [here
value() would be implemented as my_plus above]
to also yield 42, but:
        proto::eval(value(_2), meta_context(i, i+j))
would yield 10 [with a C-like overload management, other values are
also possible from my library].
The reason is that the value of value(EXPR) in the meta_context is
the value of EXPR given that it must be assigned to expression _1,
which in the
first case is j, an 8-bit quantity and in the second case is i, a 4-
bit quantity.
In the process of evaluating value(_2) another meta-expression will
be evaluated:
        mask(value(_2), left(_1)-left(_2))
which does the masking when needed.
The goal is to have the equivalent of the following in the assembly
code:
        R1 <- i
        R2 <- j
        R1 <- R1 + R2
        R1 <- R1 & 0xf
        i <- R1
for the first case and to skip the masking all together for the
second case.

It would take longer to go into the details of the fixed-point
application, but I hope the above gives you an idea of why I needed
something like 'my_plus'.

It takes some time and effort to understand how proto works, but if
you have an application that fits it is time well spent.

Regards,

                Maurizio