[nem-en] Metaphor, staging, typed reflection
Kamil Skalski
kamil.skalski at gmail.com
Mon Jan 8 21:01:46 CET 2007
2007/1/8, Sandro Magi <smagi at higherlogics.com>:
>
> > Well.. if you actually have ANY code at client side, then you need to
> > make sure that you have the update mechanism for copying new dlls to
> > the client anyways. So I just ask for a reasonable response, which is
> > safer:
> > - giving client a ready code, which will replace the previously stored
> > assembly
> > - or giving client a ready code generator, which will be executed on
> > his machine to generate the ready code?
>
> Right, so instead of a multistaged algorithm, you would have to resort
> to a compile-time macro, plus an (automated?) update distribution
> system. Not a win in overall complexity I think. :-)
So I assume that by multistaged algorithm you understand here the
system, which can detect the change in specification of... protocol,
data, presentation layout, or even the need for code change because of
existence of bug, then fetch information what needs to be updated to
apply the change and recompile code according to this update? All at
client side, with specialized protocol to inform your system that "oh,
something changed, I must recompile myself". Sounds like hell to me...
and the alternative is... damn simple http GET request plus save to
disk.
We are not yet at the stage of self modifying AIs to make it work this
way ;) We need as much simplicity during runtime after application
deployment as possible.
>
> > We have the additional flexibility, but you will never convince me
> > that JIT engine is more reliable than compiler generating target code
> > in advance.
>
> Either way you're relying on some component to generate the executable
> code, compiler or JIT. Why do you see the former as much more reliable
> than the latter? A compiler is just stage-0, and the runtime code
> generator could be the same one used as at compile-time.
Because in real life every process can fail. But if you have already
passed given process it CANNOT fail. So even if the summed result
should be the same, with runtime code generation at hand you are still
halfway to success compared to quarter way to success (both systems
could still fail because of final algorithm error).
>
> If you want assurance right down to the bare machine, either with
> compilers or JITs, then you need to resort to proof-carrying code.
>
> >> But "compile-time analysis and code generation" is exactly what
> >> intensional type analysis and multistaging is, except all the analysis
> >> can now be expressed in the host language you're compiling, and also
> >> guided by the developer!
> >
> > I don't get what you mean. So you agree that those example could be
> > pushed to compile-time instead of run-time?
>
> What I meant by the above, is that intensional type analysis is
> "compile-time analysis" of runtime behaviour, and that multistaging is
> "code generation" in your statement.
>
> > We could push our debate one level of abstraction higher:
> >
> > I state that for n-staged program it is safer, more efficient (as seen
> > by the user's experience) and more convenient during development if
> > for all stages k < n they are executed in advance at the programmer's
> > development environment.
>
> Metaphor, MetaOCaml, etc. are counter-examples. Specialized/partially
> evaluated code blocks may provide a more efficient algorithm than can be
> expressed at compile-time, just like a JIT can create fast path cases of
> an algorithm.
Ok, I withdraw the efficiency argument - the gains here are possible
of course. I also agree that in systems, where efficiency is really
critical and there is a field for improvement by JIT compilation,
delaying the next stage execution is reasonable.
I think this is a simply waged calculation - for every gained 1 bit of
efficiency / eliminating the need to distribute the ready versions you
lose 30 bits for complexity of system and 5 bits for the solution's
safety.
Big frameworks like .NET and Java can afford resources put into
developing and testing this complexity bits and then another chunk of
tests for eliminating the safety bits.
>
> As long as the properties ensured by the type system are never violated,
> it is just as safe to do this at runtime as at compile-time. Would you
> disagree?
I would disagree. Still by doing things at runtime you can stumble
upon bug not possible to catch by type system and your own tests.
>
> >> 3. then we must conclude that adding intensional type analysis and
> >> multistaging yields a safer, more efficient, more expressive language
> >> overall.
> >
> > I'm not quite sure what do you mean by this sentence...
>
> My point is that with the above two features, you can safely express
> more algorithms than you can without them. This makes it more expressive.
>
> Instead of simulating some dynamic features when you need them, you
> already have them and they're properly type checked. This makes it safer.
>
> Efficiency is an inference from the fact that partial evaluation can
> always lead to more optimized code, so it's more efficient.
>
> > Multi-staging
> > is a good tool - it gives more abstraction to the programmer and
> > allows producing more efficient code to be executed by the user. But
> > it is always safer to have system with less stages -
>
> So this is perhaps our disagreement. You agreed above that multistaging
> and macros are equivalently safe, but here you contradict yourself by
> saying fewer stages are safer.
I'm just arguing about the border line between comple/design time and
runtime. Nothing at compile-time is unsafe (in sense that it cannot
hurt your clients directly), everything in run-time is. So indeed
macros and n-stage systems are equivalently safe given then all stages
are finished at compile-time.
>
> I contend that multistaging does not introduce less safety as long as
> the type system is no weaker than it was prior to adding the staging
> extensions. How could it be?
Right - with statically-typed multi-stage system running given stage
at runtime can fail with the same probability as running it at
compile-time. But... see above.
>
> > another example
> > here is comparison of compiler and interpreter, they do actually the
> > same job for the user, allow running some code and see the results.
> > But one is MUCH more complex than the other.
> >
>
> Indeed, and yet compilers are seen as safer since they are typically
> fitted with static type systems.
>
Right, but this is a different story - about data fed into the system,
not system itself. Yet, this is a good example:
Let's assume you developed compiler and interpreter and they have the
same correctness and catch the same wrong programs.
Also, let's assume you will run known program A on them - at this
point (that is you tried this program in house on either interpreter
or compiler) this is equivalently safe.
But now assume that you will take advantage of being in runtime in
interpreter and add use the fast path for some instructions - this one
is equivalently safe for compiler case only as long as you tried the
same scenario in compiler.
The point is that the resulting code is equivalent (e.g. it is
generated by the same multistage system, but at different time of
their execution), but the process of code generation can fail. Runtime
has this ugly property, that anything unexpected can happen -
OutOfMemory exception, power surge, etc. so even when you are running
on the same tested inputs this is less reliable.
Summing up - it is true that type-safe multistage system is in theory
equivalent whatever is the "layout" of its execution, but:
- you can never assure that it will be given malicious input when
running out of your control (that is in runtime)
- you need to run it in compile time in order to inspect the real
generated code (for debugging purposes or for using it immediately as
metadata in programming environment)
- you cannot easily debug deployed system, even with much essential
data from client side, because the actually executed code is only on
client side
- you cannot avoid "unexpected" conditions during runtime
So, I also agree (as I mentioned before) that any research on the
topic is good, also about runtime code generation systems. Simply I
don't see much use for it in .NET world, especially when trying to
generate code using reflection, since ability to use reflection is a
strong signal that you could do the same at compile time.
--
Kamil Skalski
http://nazgul.omega.pl
More information about the devel-en
mailing list