>
It has the best performance and the highest level abstractions in one package.The highest level abstractions, are you kidding me?
I am currently writing a little interpreter in C++. I would have used Ocaml, but the rest of the project is in C++. Well, just try to write an abstract syntax tree in C++. In languages such as ML and Haskell, this is easy:
type expression = Litteral of value
| Symbol of string
| Funcall of expression * expression
| Conditional of expression * expression * expression
| While_loop of expression * expression
| Sequence of expression list
And I'm pretty much done. Now in C++:
--------------------------------------------------------------------------------
#ifndef __Expression_h__
#define __Expression_h__
#include <cstdint>
#include <string>
#include "Value.h"
namespace Script {
class Expression;
class Expression {
public:
enum Tag {
litteral,
symbol,
funcall,
conditional,
while_loop,
sequence
};
union Val {
Value *litteral;
std::string *symbol; // or a true symbol?
std::vector<Expression> *composite;
};
Expression(const Value&);
Expression(const std::string&);
Expression(Tag, std::vector<Expression>*); // takes ownership
~Expression();
private:
Tag _tag;
Val _val;
};
} // namespace Script
#endif // __Expression_h__
--------------------------------------------------------------------------------
Don't forget the cpp file either:
--------------------------------------------------------------------------------
#include "Expression.h"
#include <cstdio>
using namespace Script;
Expression::Expression(const Value& val)
: _tag(litteral)
{
_val.litteral = new Value(val);
}
Expression::Expression(const std::string& sym)
: _tag(symbol)
{
_val.symbol = new std::string(sym);
}
Expression::Expression(Tag tag, std::vector<Expression>* exprs)
{
if ((tag == funcall && exprs->size() == 2) ||
(tag == conditional && exprs->size() == 3) ||
(tag == while_loop && exprs->size() == 2) ||
tag == sequence) {
_tag = tag;
_val.composite = exprs;
} else {
std::fprintf(stderr, "Expression constructor: Invalid Expression\n");
exit(1);
}
}
Expression::~Expression()
{
switch (_tag) {
case litteral :
delete _val.litteral;
break;
case symbol :
delete _val.symbol;
break;
case funcall :
case conditional:
case while_loop :
case sequence :
delete _val.composite;
break;
default:
std::fprintf(stderr, "Expression destructor: broken class invariant\n");
exit(1);
}
}
--------------------------------------------------------------------------------
I may use smart pointers instead of doing my own RAII by hand, but that's still a hassle. Some may point out that my ugly unsafe union type is not the way to to this, I should use a class hierarchy and polymorphism. But just imagine the sheer amount of code I'd have to write.
C++ is a low level language. It's high level pretense is nothing but a thin veneer that cracks under the slightest scratch. Or, someone show me how to implement an abstract syntax tree in less than 20 lines of code. I'm lenient: Haskell and ML only need 6.
(Yes, I'm using Sum types, a feature that's pretty much unique to ML languages. But no, that's not cheating: providing enumeration and unions but somehow failing to combine them into sum types is a serious oversight.)