Open mingodad opened 2 years ago
Probably need to review other places where a double
is initialized with a float
.
Also for the translated C++ to give the same result the NULLC/ExpressionTranslate.cpp
need to be changed:
@@ -510,13 +510,13 @@ void TranslateIntegerLiteral(ExpressionTranslateContext &ctx, ExprIntegerLiteral
}
void TranslateRationalLiteral(ExpressionTranslateContext &ctx, ExprRationalLiteral *expression)
{
if(expression->type == ctx.ctx.typeFloat)
- Print(ctx, "((float)%e)", expression->value);
+ Print(ctx, "((float)%.9g)", expression->value);
else if(expression->type == ctx.ctx.typeDouble)
- Print(ctx, "%e", expression->value);
+ Print(ctx, "%.17g", expression->value);
else
assert(!"unknown type");
}
void TranslateTypeLiteral(ExpressionTranslateContext &ctx, ExprTypeLiteral *expression)
Hello WheretIB are you still around ? Is this project dead ?
I'm still around.
I will check your suggestions this weekend. Precision fixes sound great. But I'm not sure about syntax changes like supporting .1 yet, I will have to compare to other languages.
Thank you for reply !
I'm trying to add goto
and struct
to nullc
and changing a bit the syntax to be more close to C/C++
where possible, like I've added lex_dblcolon ::
and in this branch https://github.com/mingodad/nullc/tree/dad I have the declaration of class
members outside of a class using it instead of lex_colon
and also paln to do the same for namespaces.
There is a reason to not using the same syntax for simple/similar constructs ?
Would be nice if nullc
could accept the subset of C++ that is used to build itself.
Playing a bit with this project I've add a few nore C++ keywords, most of then are parsed and silently ignored for now, and I can execute this dummy script:
import std.io;
enum chartype
{
ct_symbol = 64, // Any symbol > 127, a-z, A-Z, 0-9, _
ct_start_symbol = 128 // Any symbol > 127, a-z, A-Z, _, :
};
inline int give5() {return 5;}
class Klass {
int _k;
static int st = 0;
public:
void Klass(int x) {
this._k = x;
}
//static
//void st_add(int x) { Klass::st += x;}
//static void st_add(int x) { this._k += x;}
//static
//int st_get() { return Klass::st;}
protected:
int get() {return this._k;}
private:
int set(int x) {int prev = this._k; this._k = x; return prev;}
//void finalize() {}
};
//static int Klass::st = 0;
//static
//void Klass::st_add(int x) { Klass::st += x;}
struct dad_t {
int x, y;
};
dad_t dt;
dt.x = 3;
dt.y = 4;
Klass klass = Klass(9);
io.out << dt.x << ":" << dt.y << ":" << int(chartype.ct_symbol) << ":" << klass._k << io.endl;
return 0;
I still need to change the parser to accept access enum
elements like in C++
-> chartype::ct_symbol
, accept C++
style constructor/destructor(finalize), accept C++
static class members, ...
With this experiment I want to see how far I can get to allow nullc
parse the C++
subset used to build itself.
Probably I would need some help in some places.
I have applied your fix to the precision of double number parsing, thank you for that.
I'm going to leave this issue open to address the changes to number parsing and to look into the remaining precision issues (maybe I'll just switch to strtod
for a full match).
Your fork looks interesting, those are some big changes. You might call it nullc++ :)
Also I found something strange when testing with exprtk
tests, when having the the tests in the global scope it takes almost twice to process than when they are inside a function see attached
exprtk_functional_test2.nc.zip
.
Do you want to join effort on it (nullc++) ? I've got template on class/struct somehow working now:
import std.io;
enum chartype
{
ct_symbol = 64, // Any symbol > 127, a-z, A-Z, 0-9, _
ct_start_symbol = 128 // Any symbol > 127, a-z, A-Z, _, :
};
inline int give5() {return 5;}
/*
template<typename T>
T createSome() {
T x = new T();
return x;
}
*/
template<typename T, classname Z>
class TName {
T name;
Z param;
};
typedef TName<char[], int> TNameCI;
TNameCI createSome() {
return TNameCI();
}
TNameCI nci = createSome();
nci.name = "dad";
nci.param = 5;
struct A extendable {
int aa;
void A() {this.aa = 0;}
int inc() {return ++this.aa;}
}
class Klass : public A {
int _k;
static int st = 0;
public:
void Klass(int x) {
this._k = x;
}
int inc() override {this.aa += 2; return this.aa;}
//static
//void st_add(int x) { Klass::st += x;}
//static void st_add(int x) { this._k += x;}
//static
//int st_get() { return Klass::st;}
protected:
int get() {return this._k;}
private:
int set(int x) {int prev = this._k; this._k = x; return prev;}
//void finalize() {}
};
//static int Klass::st = 0;
//static
//void Klass::st_add(int x) { Klass::st += x;}
struct dad_t {
int x, y;
};
dad_t dt;
dt.x = 3;
dt.y = 4;
Klass klass = Klass(9);
io.out << dt.x << ":" << dt.y << ":" << int(chartype.ct_symbol) << ":" << klass._k << io.endl;
return 0;
Also when trying to accepts constructor/destructor C++
syntax I noticed the restriction on finalizer
(destructor) for stack instances, is this a hard restriction or can it be relaxed ?
When testing nullc with the tests from https://github.com/ArashPartow/exprtk there is a big difference in the total of equal expressions compared to C/C++ or other programming languages:
Output before :
Output after:
Patch to get a better double precision and also accept numbers like
.23
,-.34
, ...:Full test source exprtk_functional_test.nc.zip