pbr vs multiple returns

new topic     » topic index » view thread      » older message » newer message

cchris005 wrote:
> 
> > Subject: Re: Digest for EUforum at topica.com, issue 6333
> > 
> > 
> > posted by: Pete Lomax <petelomax at blueyonder.co.uk>
> > 
> > CChris wrote:
> > > }}}
<eucode>
> > > function pop(byref sequence stack)
> > > object top
> > > top=stack[$]
> > > stack=stack[1..$-1]
> > > return top
> > > end function
> > > </eucode>
{{{

> > 
> > > Currently, you need to return both the modified stack and the former top 
> > > element, which is awkward.
> > 
> > FWIW, I plan something like:
> > }}}
<eucode>
> > function[2] pop(sequence stack)
> >     return stack[$], stack[1..$-1]
> > end function
> > 
> > {nextitem,stack}=pop(stack)
> > </eucode>
{{{

> > 
> > > More generally, PBR enables to transform an object, rather to return a 
> > > modified object which you have to copy onto the original - waste of CPU.
> > Technically, I plan an "unnecessary" dword move which "true" pbr
> > wouldn't; but that is trivial overhead compared to existing cow semantics
> > (in fact so trivial I very much doubt it would ever show on any timing
> > test).
> > 
> 
> Would that "dword move" also work when transforming a subscripted
> quantity, like (3]?
Hopefully, I'll know more when I start implementing it, see below.

> 
> And, by the way, would you really expect to get the modified stack in
> the returned value? I probably programmed too much in asm, but I find
> this a bit confusing. And you have to perform an extra s1=s[1] to get
> the value you need.
You seem to be confusing
return stack[$],stack[1..$-1]

with
return {stack[$],stack[1..$-1]}


So, no, I don't expect to get the modified stack "in" "the" return value,
I expect to get the modified stack as the second return value.

Internally, I plan to implement eg:
function[2] pop(sequence stack)
   return stack[$], stack[1..$-1]
end function

{nextitem,stack}=pop(stack)

as something similar to (pseudocode):
object fres1,fres2  -- virtual, of course
sequence popstack   -- scoped to pop, ""
pop:
    fres1=popstack[$]
    fres2=popstack[1..$-1]
ret

popstack=stack
stack=<no value>
call pop
top=fres1
stack=fres2

When I said "mov dword" I was referring to the last two statements, a neglible
and insignificant cost for avoiding cow overheads.

Going back to a[i]=update(a[i]), I expect that to be frighteningly difficult to
fully optimise with this multiple returns approach and may need real pbr.

But anyway, I think multiple returns are a pretty neat feature in their own
right, albeit not quite as flexible as true pbr.

> Your proposal doesn't look very good to me.
Maybe not. Let me just add that it seems Rob has gone to great lengths to
optimise say x=append(x,...) and I feel that optimisation should be generalised
so it applies to user code, not just a handful of builtins.

> 
> > 
> > > Eu has function pointers, using call_back(routine_id(rt_name)). What 
> > > confuses me is why I can't do it with variables. Am I the only one?
> > 
> > Firstly, as background, a routine_id is *utterly meaningless* to any
> > other than call_func, call_proc, and call_back. Agreed?
> > 
> 
> True. What is the issue?
I think I was trying to say that you'd never pass a routine_id to a c func,
unless you intend to have it passed back to Eu code, as C code cannot do
anything with it. Likewise variable_id would be no use to C code. I was just
trying to set the scene and make it clear I was not talking about var_id but
raw_address(var_id).

> Did you ever try to allow an external dll/piece of code to access an Eu
> variable? And do you think this is not right?
I've always used raw blocks of memory when dealing with C code.

> Using a get_this_var()/set_this_var(typeof_this_var x) pair for every
> such variable looks really like a bad idea to me. That's how we wind up
> doing it unfortunately.
Well it seems to me that call_back(get_var) and call_back(set_var) would be the
only way you could possibly manipulate Eu vars from C code. Very tricky but at
least possible. See below.
> 
> Admittedly, you an also alloocate an address (isn't this a raw pointer?)
Yes but it is not an Eu variable.
> and use this for interfacing. Only problem is that peek/poke are so darn
> slow...
Separate issue.
> 
> But indeed, my primary point was: there's a routine_id, why is a
> variable_id() any more complicated? Hence why is it not implemented?
It is a shed load more complicated.
You don't modify routines.
They don't move about.
If you do x=append(x,x) then almost always x will have been shifted somewhere
else in memory.

Consider string s="text".
In assembly this goes something like:
  dd 4  ; length
  dd 0x82000001 ; type and refcount
data db "text",0
align 4

s dd (data+1) ror 2
(see execute.h for Eu implementation, which shifts 3 and uses different high
bits, etc)

So, say we get the actual address of s and pass it to a C function. Is it goiing
to know what to do with it? Does it understand the types? Will it honour the
refcounts and clone things when needed? Will it maintain length (and base and
postfill)? When the C code craps on things, is the Eu backend going to cope/give
intelligible error messages? Will it promise not to make circular references?
Will it typecheck things it modifies? And so on.

Open this up and you completely destabalise the backend.

If you get to a point in some C code where you want to modify some Eu vars, you
are far better off invoking a call_back and doing it in Eu, imo.
The same is probably true if you just want to subscript an Eu var in C.

Regards,
Pete

new topic     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu