On Sun, Aug 19, 2012 at 11:26 PM, john skaller <
skal...@users.sourceforge.net> wrote:
>
> > It's not too late to get rid of goto, is it?
>
> What do you mean? Conditional control transfer is fundamental.
> Languages which do not provide it, providing loops or other stuff
> instead soon become even worse spaghetti.
>
Er ... I haven't seen this myself. The whole felix compiler is written
without goto - OCaml doesn't support it as far as I can tell. Do you find
its lack painful in OCaml?
I certainly don't miss it in Java, I don't use it in C/C++.
> > One can be conservative in the presence of goto and labels - which label
> you are jumping to is always hard-coded so you can simply check whether it
> is even remotely possible a var or val is not initialized and ban its use
> at any point after the label. The use of gotos should be so rare that this
> should impact almost nobody.
>
> You're misunderstanding what happens. by the time binding and type
> checking is done, there's nothing left EXCEPT gotos.
>
> Any blocks, loops, or whatever have already been replaced
> by gotos. This is how compilers work. They reduce complex things
> to simple ones.
>
Typically compilers reduce things down into a representation that is useful
to them for analysis. This is an area with which I have some familiarity.
These days programs go through several representations in the process of
optimization.
One common representation is a directed graph "basic blocks" - the
indivisible piece of code in between control flow operations along with
bi-directional links between them. From here one can consider a class of
optimizations that are safe at the basic block level, and also reason
easily about what operations come "before" and "after" a given block. If
one wants to determine whether some event can happen "in between" two
blocks they walk the graph of basic blocks
SSA also makes dependencies rather clear, as each SSA operation has a known
position. Determining whether an operation comes earlier or later depends
on that position information. You can trivially require something to be
defined before it is used. Control flow in this case is represented using
an operation that "merges" values into one based on the results of control
flow.
I don't think turning the code into a linear sequence with a bunch of
labels and gotos is very popular as it would be quite difficult to analyse
at that point.
>
> [Re: no blocks]
>
> > Are you saying you cannot do
> >
> > fun foo() = {
> > if X then do
> > return Y;
> > done
> > return Z;
> > }
> > ?
>
>
> No, of course you can do that. But the body of a function isn't a block.
> Nor is the do .. done part of the conditional a block. As in C,
> you can jump right into the middle of a do .. done. It's all straight
> line code.
>
I guess I don't know what you mean when you use the word "block".
> >
> > > I guess performance isn't THAT important to me.
> >
> > Oh yes it is, it is the ENTIRE reason for using computers!
> >
> > I meant I won't sacrifice the predictability of me code on the alter of
> performance.
>
> You don't have to! You sacrifice the predictability
> of ARBITRARY programs.
>
Heh well I don't have trouble imagining myself wanting to spawn off a bunch
of threads that make use of a variable. Sure, it's not the easiest "bug"
to reproduce, but if it's indicative of many others like it, that makes me
very nervous about using Felix for things.
> You were justifying your solution where the runtime behavior of my
application depended on decisions made by the optimiser (whether to inline
or not). That's not a worthwhile trade-off.
>
> So write Python instead.
>
I considered it, but I wanted a typed language so that it could help me
avoid errors and possibly enable some level of smartness in the IDE.
> > Define before use does not support recursion.
> >
> > This need only apply to vals and vars, functions can be recursive.
>
> This is more or less impossible in the current compiler. It uses
> a unified lookup model: all symbols all looked up by the same
> algorithm. Note types can be recursive.
>
> In general, order of initialisation cannot be determinate
> with separate compilation. Felix doesn't have that, so in theory,
> you could enforce a linear ordering.
>
> Unfortunately its very hard if not impossible to do it, without
> sacrificing something else. It may sound like it is not rocket
> science but it is in fact very hard.
>
This seems like something is already done in Java, C++, C, Scala ... the
"not used before initialized check" is being done out there, so if you
can't do it, something weird is going on. Maybe there's a feature or two
preventing it that could be cut back.
> Consider:
>
> var x = f 1;
>
> Woops! x is initialised by a function! What if it's a generator?
> What if it changes the value of something x depends on?
> What if you don't even know which function it is because
> its a closure?
>
Hey, you (we?) get to make the rules here. I'm saying there is a set of
rules that prevent a val or var from being used before it is initialized.
That might cramp one's style sometimes.
This means you cannot take the address of a var before it is declared, nor
create a closure that references that var/val.
I realized that actually you have to restrict the use of nested functions
as well, as they must be "initialized" themselves with the vals and vars
that they make use of. But they must be allowed to refer to themselves for
recursion.
Your simply "linear" ordering doesn't work.
> It doesn't work in C or C++ either. Same problem.
> Even within a single translation unit. Works better
> with vals than vars (because they're not addressable).
> Trivial with "vals not depending on vars:". If you write
> pure code its no problem.
>
What's the problem? Maybe you're talking about the order of initialization
of global variables?
That is trickier. In other places the globals are treated specially so
there's two passes, one to setup the globals and another to run your
"main". In Felix you're just putting everything at the top level so
globals are kind of just "enclosed" variables in a way.
This would introduce some significance in the order in which modules are
"included" because you wouldn't be allowed to use certain variables unless
the "global code" that initializes them has already run. It doesn't seem
too unbearable but definitely a bit more of a pain.
Reordering these things at the compiler level might not be acceptable if
they depend on a generator or something that modifies global state.
> May or may not trigger a DIVBYZERO error depending on the optimizer's
> decisions at compile time. I don't want this function to work perfectly
> for years and then one day, due to some little optimizer tweak or someone
> exceeding the inlining threshold, it starts causing the program to abort.
>
> Then do not use vals. User vars instead.
>
> > That's just not what I would consider a "safe" programming language.
>
> It's not meant to be entirely safe: that's impossible anyhow.
>
Well, not even particularly "safe"-ish.
> > It increasingly appears that you have little interest, however, in
> safety - your interest in types stems only from an interest in performance.
>
> I'm very interested in safety. I have never disputed that any of the
> things
> that you find disturbing are a problem.
>
> They disturb me too. I just don't know how to fix them.
>
Ah, hmm it seemed in a few cases you were saying that these were not a
problem ...
Well, if they're on the "known issue" list I don't mind as much. It means
that I could try to fix some of them if they get in my way.
> Slowing down unrelated things just to achieve safety
> isn't a good compromise though. I have looked at quite a lot
> of possible solutions and none of them work.
>
We may need to have some kind of definition or test case around how fast
things are so one could determine whether things had in actual fact been
slowed down. Then changes to turn on/off certain optimizations can be
measured for their effects, rather than taking a guess at the impact of an
optimization. Well, maybe you've already been doing that, I don't know.
In my experience, most of the optimization goes to waste because your
application is I/O bound. Some fields are an exception - compilers,
mathmetical simulations, and whatnot are not the bread and butter of the
software industry and they will turn to tools like Fortran and whatnot to
get that extra bit of performance. Not me, though! I'd go as far as using
C++ if Felix doesn't work out for me, but not all the way to Fortran.
So, some thought about who the primary audience is might be helpful. If
it's the people who really need to save every last cycle then by all means
alienate everyone else to serve them. If you're eyeing the mainstream then
CPU cycles are cheap and programmer time not so. So a predictable,
consistent, and familiar operational model will be very important.
> In addition, I don't have full control over everything due to a prior
> commitment to stick to the C/C++ object model. Instead of,
> for example, doing what the Ocaml team did: generate
> machine code.
Yes, I can see that is a double-edged sword. But it is a distinguishing
feature of Felix, in a way, and I like the interoperability.
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Felix-language mailing list
Felix-language@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/felix-language