Re: object system...
- From: "cr88192" <cr88192@xxxxxxxxxxx>
- Date: Thu, 15 Jan 2009 10:13:54 +1000
"Dmitry A. Kazakov" <mailbox@xxxxxxxxxxxxxxxxx> wrote in message
news:12cbzc4j7mkdd.1hdv3ksqztptf.dlg@xxxxxxxxxxxxx
On Thu, 15 Jan 2009 00:23:07 +1000, cr88192 wrote:
"Dmitry A. Kazakov" <mailbox@xxxxxxxxxxxxxxxxx> wrote in message
news:163b2w1jiz24c$.115zwvzcu6sr7.dlg@xxxxxxxxxxxxx
On Tue, 13 Jan 2009 23:54:00 +1000, cr88192 wrote:
"Dmitry A. Kazakov" <mailbox@xxxxxxxxxxxxxxxxx> wrote in message
news:1obq05ayl19zl$.mghpopxh028w.dlg@xxxxxxxxxxxxx
On Mon, 12 Jan 2009 22:50:28 +1000, cr88192 wrote:
4. when rebuilding the code. in this case, usually the type
information
is kept purely as sideband or scaffolding, and once the code is built
it ceases to matter, or at least until more code needs to be built
around it..
Same as 3, the context must know the type where an operation on it
should happen. Context /= object /= type.
only when the code already exists at compile time...
if the code does not exist, it can't be typed at this point, and so the
information needs to be kept around until it can be used...
Yes, for a compiler the program is a text.
only to the parser...
Parser is an optional part of the compiler.
yes, but it is very useful when input is given as text...
in general I tend to drive my code more through textual / printf-style
interfaces, than by directly giving ASTs or bytecode.
a partial reason for this is that it is usually easier to keep the parts
decoupled via a textual format than via a binary one, or by direct code
interaction (this is especially the case when the serialize and deserialize
process in itself causes a transformation, such as to flatted down one tree
and rebuild a new differently-organized structure at parse-time).
then it is ASTs, an IL format, ASM, ...
This changes nothing.
a compiler is more than just a parser, that was the main point...
no, the OS only knows about apps after they are installed...
Yes, that is the behavior of "application type." <=> it knows
applications.
FWIW, the OS can be compared to a huge self-modifying program
No, it cannot be. Depending on what one understands under "system," does
this includes non-volatile memory etc. In any case, once you draw a line
and define what parts belong to the system, you will immediately see, that
it is not self-modifying. There is no such thing as self-modifying
programs, you always need an external agent, which does not change.
my code tends to be self-modifying, or not, in much the same as the OS, only
that it is done at a much finer level.
so, yes, my approaches tend to be much more about loading and/or building
code, than about tweaking existing code ("patching" is possible, but I don't
use it nearly as often as to just build more code and link it against the
prior code, ...).
but, then the new code is still integrated at the data-level with the
original (via structures, function pointers, ...), and we can call function
pointers, so the program can be considered modified in this respect.
a compiler is, however, a much more powerful component than a module loader,
since the compiler can produce new code as needed (as the result of
pre-existing code-writing functions, ...), whereas a module loader only
loads pre-compiled code...
none the less, I use module loading as well, for the main reason that it is
much faster to load a module than compile it (especially with C, which
includes a few majorly expensive issues in the compilation process...).
a goal would be to be able to get all this good enough and efficient enough
that "eval" could become a practical feature (at present, eval with C would
just be impractically expensive... leaving me at present doing most
eval-like tasks in assembler, but even this is an improvement over
before...).
but, there is no need for it to compile (all of) itself, because the
external compiler (AKA: static compiler and linker) has already done
so...
And the compiler does not change... Barber does not shave himself...
the compiler does not usually need to change itself, as it can be regarded
as a component, but it may then be used by the code it has compiled in order
to produce new code...
it does not bother me that much that the OS leaves the statically compiled
parts of '.text' as read-only...
now, as for the barber:
it is a paradox if both possibilities are to be considered at the same
time
(as in an axiom), however if on each day he makes this same decision
(using
the prior day as his current status, as is more typical in procedural
logic), then he will only shave every-other day (the axiom will be true
at
one try, but false at the next, then true, then false, ...).
He does not make decisions, he makes a statement about decisions. This
statement is self contradictory and thus cannot be used as a basis for
decision making. Other statements could be.
yes, I guess one would have to change the "does" to "did" to really make
this work...
but, as I see it, many paradoxes can exist, only that they result in an
alternating binary pattern...
however, apparently "logic" in its pure form is not my area of empasis (my
world is much more of a big mass of interacting machinery and state than it
is logic...).
in psychological terms, this would seem to be a matter of Ti vs Te or
similar (whether the person uses introverted or extraverted thinking, ...).
maybe I will leave it as a mysetery, but I think I use Te...
but then again, I see myself under my own way of seeing things, ...
however, as can also be noted, software is based on code, not on abstract
logic...
Well, that is an interesting statement. It is business logic I guess? If
your software is not based on formal logic, then you cannot reason about
it
in formal terms. My condolences...
it is based on behavior...
one considers the behaviors that will be exhibited as one feeds in a whole
range of inputs, abstractly considering the input space and the output
space, much like light through a lens or prism...
so, the central aspect is the algorithm, anything works so long as an
algorithm can be made for it, ...
but, then one has to learn not to regard their social life this way, as this
seems to make people unhappy, ... (so, it is like, oh yes, the rather alien
and confusing world of emotions, which is only visible maybe rarely, ... but
is much more central to most peoples' lives and behaviors than would have
naturally been expected, ...).
if we say that in reality the types do not exist, but are merely
manifestations of the present state, then there is not a problem with
saying
that a type is represented by a type...
Where that follows from? Existence in "reality" is irrelevant to the issue
of consistence. Does reality exist?
a type is a logical construct, rather than a physical one, and so if a type
is in conflict, but the physical object exists, one opts with the physical
object. logic is naturally opposed to cyclic dependencies and systems,
whereas physical reality contains them in abundance (as self-reinforcing
patterns...).
but, yes, a relevant phrase here is "I think therefor I am", which could be
reworded: "if I did not exist I could not consider whether or not I exist".
and, so, the existence of reality can be asserted, even as lacking as the
substance of this existence would seem to be at times (for example, that
everything that exists, has this existance based primarily on state, and
that apart from state there is no form either...).
so, taken further, existance can be asserted to exist as an "absolute",
because if it did not exist at any other point along the chain, it would not
exist "here" either...
similar reasoning can also be used for the existence of morals, ...
but, then one can debate whether or not this existence is absolute or
relative, the structure and form in which it all exists, ... (allowing for a
world/truth which is at the same time both relative and absolute, where the
form becomes relative, and anything can be considered as true so long as it
can be reconciled with those things which can be said to exist...).
for example, it is reasonable to describe the sun and stars from a
geocentric perspective, or through the use of analogies and symbolism, and
still regard this as true, but this is limited at which point they come in
conflict with the actual sun and stars (so, a person can correctly describe
them by analogies, but at which point they say that these analogies ARE the
objects they refer to, then the statements are no longer correct).
so, the sun could be said to rise in the east and set in the west, but it is
incorrect to say that the sun orbits the earth (and it is not in conflict to
assert at the same time that the earth orbits the sun, and also that the sun
rises and sets).
or, by the same definition, a compiler for C++ can't be written in C++,
since it would have to compile itself, but oh wait, this is the whole
point
of writing the compiler in its own language...
This is a different issue. You write a compiler, the compiler writes
nothing. Same as a program printing its own code is not
self-contradictory.
But reasoning about own behavior is. So halting problem goes. Typing
system
is reasoning about behavior. A self-referential type system will
inevitably
become inconsistent, at some point. So it is dangerous to play with this
stuff. An inconsistency will manifest itself in incomputability of some
operations, i.e. your system will either hang or else crash after eating
all available memory. BTW, most of compilers suffer this.
and then enters the occasional need to insert checks into code to deal with
cyclic issues...
but, yes, for other reasons, memory usage becomes a major hassle with a
system of this sort.
sadly, maintaining metadata about the workings of a system is not cheap,
which becomes another problem when dynamically compiling C code:
preventing the garbage collector from going berserk (which is of no real
help to the pre-existing slowness of the whole process...).
the idea is to try to find alternative strategies that are both faster and
more conservative with heap (for example, an in-memory precompiled-header
mechanism, finding ways to allow reusable toplevels/environments for dynamic
code compilation, ...).
so, yes, a big problem with all of this is trying to make it all a lot more
practical, ... while still not too much confining its capabilities (a
compiler that could only ever compile C, and in a single way, would be
sad...).
it is declared against a class but it uses the instance.
This is another case. If a polymorphic object is declared, then it is
an
instance of the type which is a transitive closure of the class. I
don't
know which case you mean, polymorphic or a non-polymorphic one.
I am not sure what is being said here...
Because class cannot be a type, you need some distinct type to represent
the class. The set of values of the type is a closure of the values of
types from the class.
structs, strings, ...
now, there are more direct versions of this wonkiness:
consider SmallTalk;
classes are first class objects (aka: instances) of prior existing
classes
(aka: classes are needed to represent their own representation).
now, how ST implementations pull this off in practice, I am less certain,
but I am aware of this bit of amusing trivia...
I don't know how they do it. I think it is impossible to without some
acrobatics...
I presume something is used, but I don't know the details either...
it is not declared against the instance, nor is it used against the
class...
When object is not declared to have a type related to the interface,
then any operation of the interface applied to the object is a type
error.
In a consistent strong typed system, you just cannot do these things.
That is the idea of strong typing, not to allow this mess.
again, this does not make sense.
To break types indeed does not make sense. The point is, that if you
tried
to formalize the stuff we discuss, you would quickly discover that you
could not do it. It is inconsistent like "all Cretans are liars."
formalisms don't matter so much as long as the code is working...
1. How do you know that it does?
2. How do you know that it will do?
1. testing...
2. considering its behavior / implementation as the fundamental aspect...
for example, the "logic" of a piece of code can be rather broken, but the
behaviors are still classifiable. as has been said about some code/... in
the past "it's not a bug, it's a feature...".
do you use an interface to access static methods?...
Static method? If you mean C++ static member, that is an artefact of its
poor design, which confuses visibility issues with types.
close enough... I meant like Java and C# static methods, where the class
can
be accessed apart from its instance...
What for? If type is not a first-class citizen you cannot do anything
useful with it anyway.
both allow some methods and fields to be called without instancing the
object, these being static fields and methods (in contrast to
instance-fields or virtual functions, which require an instance...).
but, one can't use an interface to access a class by itself, and it does not
make much sense to do so...
I may put a little more weight into this claim if evidence can be
shown,
or at least a justifiably solid explanation is given...
"compiler can choose" does not necessarily mean "faster"...
maybe it means "can omit bounds check", but C does not use these
anyways
(and more recent compilers, such as those for C#, are in many cases
able
to figure out when to leave out the bounds check).
It can use a shorter machine type for the index instead of int. When you
specify int, the compiler does not know if this int is "as-is" or else
an
implementation artefact, and unsigned char would go as well. To check
such
issues is a heavy burden and is theoretically incomputable at all.
Furthermore, the compiler can use indexing machine instructions which
may
have no explicit index at all. Because the index range is known the
compiler could load the whole array into a cache etc.
and you are saying an unsigned char would be faster for an array
index?...
I don't know it, as a programmer. I don't even want to know it. It is not
my business. I say what I want and the compiler has to do best of it. It
is
an absolutely different programming paradigm: higher level vs. lower
level.
ok.
many other people think of HLLs mostly as a way of glossing over or
contracting down the size of a large number of issues, for example, C gives
much more portability than ASM, and requires writing far less code, but at
the cost that many tasks are not possible within C, requiring one to fall
back to ASM in order to pull them off (in particular, C by itself is not
reflective, and gaining reflection in C requires using a good deal of ASM
code, loading lots of data from files, ...).
When you expose machine types, you cannot describe their semantics
in a machine-independent way, obviously.
doesn't matter when the machines in question implement more-or-less
the same semantics...
How do you define "more or less same semantics?" Computing is
discrete, 1+1 is either 2 or else wrong. Does 15326+35221 overflow?
you know... 2+2=5...
whether or not numbers overflow depends on their sizes and other
factor.
It depends on the type of. If you lack this information in types you
cannot write a program with defined semantic.
In Ada I write:
type T is range 1..2;
this instructs the compiler to implement a semantics that makes
impossible
to assign 2+2 to a variable of the type T.
yes, but typically the compiler usually does not need to know this.
It usually does, because using of built-in types is discouraged.
what kind of reason is that?...
A well-defined semantics and everything that follows:
1. Portability
2. Efficiency
3. Maintainability
4. Safety
5. Verifiability
ok.
yes, granted the above are not good reasons for using C...
this is partly why the JVM and CIL are useful tools, since one can produce
code which is possible to be verified or sandboxed...
yet, both tend to use built-in fixed-size types, so the question is whether
the feature in question can deliver these benefits over, for example, what
is possible in the JVM or CIL?...
in most mainstream languages, they are not discouraged.
in fact, they are the only things offered.
(:-)) You know, the mainstream languages are quite miserable, and the
current state of software developing is even worse.
maybe, but it goes forwards at a fast pace...
lots of people writing software, then rewriting software, making more
software, ...
all that is needed to know is that the types are big enough to hold the
values in question, and if there is an overflow, that is the
programmers'
problem (or, possibly, the fault of whoever it was trying to compile
the
code on whatever arch it does not work on...).
Everything is programmer's problem. The argument of "big enough" is
plain
wrong. Consider a modular type with circular shift operation as a
counterexample.
if one needs a circular shift, it can be implemented easily enough with
existing types.
for example, a 20 bit circular left-shift:
v=((v<<i)&((1<<20)-1))|((v>>(20-i))&((1<<i)-1));
or, a right shift:
v=(((v&((1<<20)-1))>>i)|((v<<(20-i))&((1<<20)-1));
now, these could be wrapped nicely in macros, and there is no need for
some
funky type...
Nope, you forgot the rest of ring arithmetic:
a+b mod 20
a*b mod 20
...
20 bits, not base 20...
(a+b)&((1<<20)-1)
(a*b)&((1<<20)-1)
And sorry, do you call it a language?
?...
Anyway, the point is, when you add values to the type, you get another
type. The argument about safe ranges is bogus.
The right technical term is substitutability = preservation of all
propositions about all possible programs using the type. Substitutability
does not hold even with safe ranges. That means, each time when you
replace
one type with a machine type you have to analyse each use case of.
one can consider that a 32-bit integer has 32 bits, and usually that seems
sufficient to consider its behavior...
part of its behavior may also be overflow, although personally I feel it is
not a good idea to base algos around particular overflow behavior / ...
(apart from the use of explicit masking), since it could introduce bugs if
more bits are used internally (for example, smaller types may actually
periodically be represented as bigger types, and then re-contracted later,
creating the possibility that overflowed bits might still be in use).
so, we may have a few rare algos which use 32-bit integers but confine the
operating range to 28 or 30 bits (or even 16 bits for some operations). but,
mostly this is when implementing bignums, which are something better off
implemented in assembler if possible (an ASM-based int128 multiply or divide
is almost invariably faster than a C-based multiply or divide).
another option then is to use 32 bit values, but implement some algos using
64 bit values internally (it is a tradeoff on x86...).
sadly, float128 operations are a bit more complicated, and so I have yet to
write specific ASM versions of the operations...
it can also be noted that most processors wont have built-in operations
for
these cases anyways (and many expressions in the above would likely be
reduced to constants by the compiler).
Exactly, this is why I want the compiler to implement the semantics of,
instead of writing tons of macros, so typical to C.
but, these sort of features don't come free...
to use something of than C is to use something other than C, as it were...
more so, for many tasks, how can one justify using a language like Ada
anyways?...
Do you mean technical or economical justification? We just do not have
enough staff and time to develop reusable software in C++. It is too
expensive and risky to write high integrity software in C++. (We still
develop about 70% in C++, alas)
well, I guess it depends some on domain then.
Well, if your customers accepted any rubbish, you could use random
generator in order to produce code... (:-))
actually... some of my algos are based on using random number generators...
much like hash tables can have almost magical abilities to make code faster,
random number generators can have almost magical ability to make many
self-organizing constructs...
for example, random number generators are used in some places in my
compiler, ...
in general I try to implement TRNG's though, since PRNGs don't offer much
advantage over deterministic code. I usually use varried approaches for
accumulating entropy, one particular approach is that of "clock
masturbation" (basically, noting that there tends to be a good deal of
non-deterministic noise in some operations, such as 'rdtsc', and so one can
periodically mine chunks of entropy off of the processor and feed this back
into the RNG state).
they don't exhibit exactly the same properties, so TRNGs have many properies
that make them useful for many algorithms, but PRNGs have properties that
make them much more useful for some other algos (it depends mostly on
whether one needs a non-deterministic entropy source, or whether the
determinism of a deterministic PRNG would be more useful, since one can
exactly repeat the sequence if needed, ...).
so, for example, one can note that hashing and PRNGs are similar, so one can
use a PRNG for tasks like organizing code and data, ... and watch as it
manages to do so more efficiently than a more conventional algo would, ...
one can also use genetic algorithms, but the problem with these is that they
are both too slow and too limited to really be of much use for solving most
practical problems...
none the less I include some code for both GAs and NNs in my library code,
as there are rare cases where they are useful (one just doesn't want to use
GAs for anything where they need the answer in a reasonable amount of time,
and NNs aren't really applicable to most problems...).
for example, how good of support does it have for DirectX, OpenGL, Win32
API, ... ?...
No problem, though we don't use either.
how effortlessly does it share data with C, C++, ?...
No problem.
how good is it at implementing customized memory management, VMs, and
self-modifying code?...
Memory management is no problem. VM is a possible target. Code management
is solvable using partitions.
how about easily doing copy/paste porting between languages?... (this is
a
major win for many of the mainstream languages, since the similar syntax
in
many cases keeps the porting effort fairly low in many cases...)
...
We don't port from C. But there are tools (like c2ada) that do it. Though
in many cases it does not worth the efforts. C code usually suffers a huge
amount of manual micro optimization, which make it unusable.
yeah...
it is just common practice I guess for people to copy/paste code fragments
off the internet, and then port to their language of choice...
if the languages are significantly different, then this is much less
practical...
if the answers are "more effort than C and C++", then there is a
problem...
Huh, did you ever try to port a MSVC++ application into Borland C++, or
reverse? Or at least to make one that will be compilable under both?
I have before taken some of my code that builds fine with Cygwin and MinGW
and built it with MSVC before, but usually I don't have much reason to use
MSVC...
The answer is much less efforts. This is the major reason why we chose
Ada.
now, can you convince the rest of the world of this?...
to face them effectively, a language has to be without any major
detractors,
with integration issues being minimal, and while still offering a general
improvement over many of their shortcommings.
Yes, yes, switching from Visual Studio 2003 to Studio 2005, been there,
have a shirt...
yes, this is an example...
or C to C++, or C++ to C# (ok, there are some detractors of C# vs C++ as
well, but for many things there can be argued to be improvement...).
so, I figure, rather than trying to replace what exists, I will just try
to
absorb it, while still hopefully making some improvements in the process
(this is the hard area, as it is difficult to implement things without
their
implementation sucking, but if one tries to at least implement it
reasonably
faithfully, that is probably ok...).
My impression is that this is likely impossible, to much clutter and
impedance. I think that maybe a better approach is a heterogeneous
middleware which could bridge the parties. Considering networking and
incoming massively multi-core architectures, this stuff will come this or
that why. So why not to use it as a glue on the same processor?
hetrogeneous middleware is a good way of absorbing things.
one can patch into it, and partly influence the internals, so it has, FWIW,
been "absorbed" into the mass...
not like one has to change the representation of what exists, only to be
able to grab it and use it...
of course, at the low-level, this does mean a lot of custom code and
emulation (for example, writing compilers for several languages, JIT
machinery for several different bytecode, ...).
so, as of yet, for example, Eclipse will not run on top of my project, but
it may do so eventually...
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
.
- Follow-Ups:
- Re: object system...
- From: Dmitry A. Kazakov
- Re: object system...
- References:
- object system...
- From: cr88192
- Re: object system...
- From: Dmitry A. Kazakov
- Re: object system...
- From: cr88192
- Re: object system...
- From: Dmitry A. Kazakov
- Re: object system...
- From: cr88192
- Re: object system...
- From: Dmitry A. Kazakov
- Re: object system...
- From: cr88192
- Re: object system...
- From: Dmitry A. Kazakov
- Re: object system...
- From: cr88192
- Re: object system...
- From: Dmitry A. Kazakov
- Re: object system...
- From: cr88192
- Re: object system...
- From: Dmitry A. Kazakov
- Re: object system...
- From: cr88192
- Re: object system...
- From: Dmitry A. Kazakov
- Re: object system...
- From: cr88192
- Re: object system...
- From: Dmitry A. Kazakov
- Re: object system...
- From: cr88192
- Re: object system...
- From: Dmitry A. Kazakov
- Re: object system...
- From: cr88192
- Re: object system...
- From: Dmitry A. Kazakov
- object system...
- Prev by Date: Re: object system...
- Next by Date: Re: object system...
- Previous by thread: Re: object system...
- Next by thread: Re: object system...
- Index(es):
Relevant Pages
|