From: | "Chris Morley" <chris.morley@lineone.net> |
Newsgroups: | comp.compilers |
Date: | Mon, 25 Aug 2008 10:24:21 +0100 |
Organization: | Zen Internet |
References: | 08-08-050 |
Keywords: | types, optimize |
Posted-Date: | 25 Aug 2008 08:15:55 EDT |
> Id temp = IS_INT(j) ? j * 5 : call(j, "mult", 5);
> Id i = IS_INT(temp) ? temp + 3 : call(temp, "add", 3);
>
> Where IS_INT is some macro that would do some bit-check to verify that
> the object can be interpreted as an int.
>
> Aside from being hideously ugly, I am not really sure that it is a
> workable solution.
>
> This obviously touches on the whole "how do you get a dynamic language
> to run as fast as C" discussion. So, does anyone have any ideas or
> pointers?
I wrote a script language (to write repetitive source code from a
template) which is C like, has user defined variables and all type
control is done at runtime. I wrote it in C++ & used normal virtual
fns to dispatch the operators and perform type conversion. The parser
creates a basic tree which is then interpreted & the function calls
really aren't an issue for my performance.
Essentially I coded the 'generic' case of what you suggest. A basic
outline of what I did is below, of course you can splatter it with
consts etc. to your hearts content...
class Base {
public:
virtual Int* GetAsInt() {return NULL;} // return Int or NULL if
conversion illegal
virtual String* GetAsString();
virtual void BinaryPlus(Base* rhs);
...
}
class Int : public Base {
public:
Int* GetAsInt() {return this;} // No conversion
String* GetAsString(); // makes new string & initialises it with
formatted Int
void BinaryPlus(Base* rhs) {
Int* int_rhs=GetAsInt(rhs); // conversion
if (!int_rhs) SemanticError(); // Error handling
Val += int_rhs->Val; // do operator;
}
private:
int Val;
}
//elsewhere...
ExectueTreeNodeBinary {
...
lhs->BinaryPlus( rhs ); // all done - in fact here I use a generic
dispatch fn with a pointer to the Binary Operator, no switch or anything
}
Types only need to know about themselves & how to convert themselves
to other types (if possible). It gives me the benefit that I can add
integers to strings and get a string which is great for text
formatting (the purpose of my language). 2 trivial vfn lookups for a
binary operator really isn't a performance problem on modern
processors. I prefer it to branches & switches.
So for:
int i = j * 5 + 3;
I have the obvious tree based on C operator precedence. So instance j
operator* is called with rhs constant(5) which is converted to j's
type as the above example before the *. Then constant(3) is converted
to result's type (i.e. j's type) for the binary+. Then the result is
converted to int for the assignment. Any illegal semantics in the
types are mopped up along the way + useful error message for the human
overlord.
In fact the common code for the operators is pulled out into a wrapper fn()
& the binary operators (unary as well) are much simpler in my real types but
I hope you get the gist. Performance is good but simplicity of implementing
operators & types was my primary concern.
I assume that your application & requirements are different to mine but I
hope the info is helpful.
Chris
Return to the
comp.compilers page.
Search the
comp.compilers archives again.