Esc now supports int64

git-svn-id: svn://ultimatepp.org/upp/trunk@7686 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2014-09-14 08:35:07 +00:00
parent 862cffc36a
commit b417b9443b
6 changed files with 185 additions and 61 deletions

View file

@ -28,7 +28,7 @@ EscValue Esc::Get(const SRVal& val)
{
LTIMING("Get");
if(skipexp)
return 1;
return (int64)1;
EscValue v = val.lval ? *val.lval : val.rval;
if(val.sbs.IsArray()) {
const Vector<EscValue>& sbs = val.sbs.GetArray();
@ -42,7 +42,7 @@ EscValue Esc::Get(const SRVal& val)
if(ss.IsArray() && ss.GetArray().GetCount() >= 2) {
EscValue v1 = ss.ArrayGet(0);
EscValue v2 = ss.ArrayGet(1);
int i = v1.IsInt() ? v1.GetInt() : 0;
int i = v1.GetInt();
int n = count - i;
if(ss.GetCount() == 2)
n = v2.IsInt() ? v2.GetInt() : n;
@ -60,11 +60,11 @@ EscValue Esc::Get(const SRVal& val)
ThrowError("slice out of range");
}
else {
int i = Int(ss, "index");
int64 i = Int(ss, "index");
if(i < 0)
i += count;
if(i >= 0 && i < count)
v = v.ArrayGet(i);
v = v.ArrayGet((int)i);
else
ThrowError("index out of range");
}
@ -99,12 +99,12 @@ void Esc::Assign(EscValue& val, const Vector<EscValue>& sbs, int si, const EscVa
if(si < sbs.GetCount()) {
if(ss.IsArray())
ThrowError("slice must be last subscript");
int i = Int(ss, "index");
int64 i = Int(ss, "index");
if(i >= 0 && i < val.GetCount()) {
EscValue x = val.ArrayGet(i);
val.ArraySet(i, 0.0);
EscValue x = val.ArrayGet((int)i);
val.ArraySet((int)i, 0.0);
Assign(x, sbs, si, src);
if(!val.ArraySet(i, x))
if(!val.ArraySet((int)i, x))
OutOfMemory();
return;
}
@ -136,11 +136,11 @@ void Esc::Assign(EscValue& val, const Vector<EscValue>& sbs, int si, const EscVa
ThrowError("slice out of range");
}
else {
int i = ss.IsVoid() ? val.GetCount() : Int(ss, "index");
int64 i = ss.IsVoid() ? val.GetCount() : Int(ss, "index");
if(i < 0)
i = count + i;
if(i >= 0) {
if(!val.ArraySet(i, src))
if(i >= 0 && i < INT_MAX) {
if(!val.ArraySet((int)i, src))
ThrowError("out of memory");
return;
}
@ -300,11 +300,11 @@ void Esc::Term(SRVal& r)
op_limit--;
TestLimit();
if(Char2('0', 'x') || Char2('0', 'X')) {
r = ReadNumber(16);
r = ReadNumber64(16);
return;
}
if(Char2('0', 'b') || Char2('0', 'B')) {
r = ReadNumber(2);
r = ReadNumber64(2);
return;
}
if(IsChar2('0', '.')) {
@ -312,10 +312,11 @@ void Esc::Term(SRVal& r)
return;
}
if(Char('0')) {
r = IsNumber() ? ReadNumber(8) : 0;
r = IsNumber() ? ReadNumber64(8) : 0;
return;
}
if(IsNumber()) {
// TODO: int64 !
r = ReadDouble();
return;
}
@ -327,7 +328,7 @@ void Esc::Term(SRVal& r)
WString s = FromUtf8(ReadString('\''));
if(s.GetLength() != 1)
ThrowError("invalid character literal");
r = s[0];
r = (int64)s[0];
return;
}
if(Char('@')) {
@ -444,11 +445,11 @@ double Esc::Number(const EscValue& a, const char *oper)
return a.GetNumber();
}
int Esc::Int(const EscValue& a, const char *oper)
int64 Esc::Int(const EscValue& a, const char *oper)
{
if(!a.IsInt())
if(!a.IsInt64())
ThrowError(String().Cat() << "integer expected for '" << oper << "', encountered " << Lims(a.ToString()));
return a.GetInt();
return a.GetInt64();
}
double Esc::Number(const Esc::SRVal& a, const char *oper)
@ -456,7 +457,7 @@ double Esc::Number(const Esc::SRVal& a, const char *oper)
return Number(Get(a), oper);
}
int Esc::Int(const Esc::SRVal& a, const char *oper)
int64 Esc::Int(const Esc::SRVal& a, const char *oper)
{
return Int(Get(a), oper);
}
@ -465,27 +466,43 @@ void Esc::Unary(Esc::SRVal& r)
{
if(Char2('+', '+')) {
Unary(r);
Assign(r, Number(r, "++") + 1);
EscValue v = Get(r);
if(v.IsInt64())
Assign(r, Int(v, "++") + 1);
else
Assign(r, Number(v, "++") + 1);
}
else
if(Char2('-', '-')) {
Unary(r);
Assign(r, Number(r, "++") - 1);
EscValue v = Get(r);
if(v.IsInt64())
Assign(r, Int(v, "--") - 1);
else
Assign(r, Number(v, "--") - 1);
}
else
if(Char('-')) {
Unary(r);
r = -Number(r, "-");
EscValue v = Get(r);
if(v.IsInt64())
r = -Int(v, "-");
else
r = -Number(v, "-");
}
else
if(Char('+')) {
Unary(r);
r = Number(r, "+");
EscValue v = Get(r);
if(v.IsInt64())
r = Int(v, "+");
else
r = Number(v, "+");
}
else
if(Char('!')) {
Unary(r);
r = !IsTrue(Get(r));
r = (int64)!IsTrue(Get(r));
}
else
if(Char('~')) {
@ -497,12 +514,18 @@ void Esc::Unary(Esc::SRVal& r)
if(Char2('+', '+')) {
EscValue v = Get(r);
Assign(r, Number(v, "++") + 1);
if(v.IsInt64())
Assign(r, Int(v, "++") + 1);
else
Assign(r, Number(v, "++") + 1);
r = v;
}
if(Char2('-', '-')) {
EscValue v = Get(r);
Assign(r, Number(v, "--") - 1);
if(v.IsInt64())
Assign(r, Int(v, "--") - 1);
else
Assign(r, Number(v, "--") - 1);
r = v;
}
}
@ -536,6 +559,9 @@ void Esc::Mul(Esc::SRVal& r)
else
if(y.IsArray() && x.IsInt())
r = MulArray(y, x);
else
if(x.IsInt64() && y.IsInt64())
r = Int(x, "*") * Int(y, "*");
else
r = Number(x, "*") * Number(y, "*");
}
@ -543,16 +569,18 @@ void Esc::Mul(Esc::SRVal& r)
if(!IsChar2('/', '=') && Char('/')) {
SRVal w;
Unary(w);
double b = Number(w, "/");
EscValue x = Get(r);
EscValue y = Get(w);
double b = Number(y, "/");
if(b == 0)
ThrowError("divide by zero");
r = Number(r, "/") / b;
r = Number(x, "/") / b;
}
else
if(!IsChar2('%', '=') && Char('%')) {
SRVal w;
Unary(w);
int b = Int(w, "%");
int64 b = Int(w, "%");
if(b == 0)
ThrowError("divide by zero");
r = Int(r, "%") % b;
@ -576,14 +604,23 @@ void Esc::Add(Esc::SRVal& r)
r = v;
}
else
if(!(v.IsArray() && b.IsVoid()))
r = Number(v, "+") + Number(b, "+");
if(!(v.IsArray() && b.IsVoid())) {
if(v.IsInt64() && b.IsInt64())
r = Int(v, "+") + Int(b, "+");
else
r = Number(v, "+") + Number(b, "+");
}
}
else
if(!IsChar2('-', '=') && Char('-')) {
SRVal w;
Mul(w);
r = Number(r, "-") - Number(w, "-");
EscValue v = Get(r);
EscValue b = Get(w);
if(v.IsInt64() && b.IsInt64())
r = Int(v, "-") - Int(b, "-");
else
r = Number(v, "-") - Number(b, "-");
}
else
return;
@ -620,8 +657,10 @@ void Esc::Shift(Esc::SRVal& r)
double Esc::DoCompare(const EscValue& a, const EscValue& b, const char *op)
{
LTIMING("DoCompare");
if(a.IsInt64() && b.IsInt64())
return SgnCompare(a.GetInt64(), b.GetInt64());
if(a.IsNumber() && b.IsNumber())
return a.GetNumber() - b.GetNumber();
return SgnCompare(a.GetNumber(), b.GetNumber());
if(a.IsArray() && b.IsArray()) {
const Vector<EscValue>& x = a.GetArray();
const Vector<EscValue>& y = b.GetArray();
@ -807,37 +846,53 @@ void Esc::Assign(Esc::SRVal& r)
}
else
if(!(v.IsArray() && b.IsVoid()))
Assign(r, Number(v, "+=") + Number(b, "+="));
if(v.IsInt64() && b.IsInt64())
Assign(r, Int(v, "+=") + Int(b, "+="));
else
Assign(r, Number(v, "+=") + Number(b, "+="));
}
else
if(Char2('-', '=')) {
SRVal w;
Cond(w);
Assign(r, Number(r, "-=") - Number(w, "-="));
EscValue v = Get(r);
EscValue b = Get(w);
if(v.IsInt64() && b.IsInt64())
Assign(r, Int(v, "-=") - Int(b, "-="));
else
Assign(r, Number(v, "-=") - Number(b, "-="));
}
else
if(Char2('*', '=')) {
SRVal w;
Cond(w);
Assign(r, Number(r, "*=") * Number(w, "*="));
EscValue x = Get(r);
EscValue y = Get(w);
if(x.IsInt64() && y.IsInt64())
Assign(r, Int(x, "*=") * Int(y, "*="));
else
Assign(r, Number(x, "*=") * Number(y, "*="));
}
else
if(Char2('/', '=')) {
SRVal w;
Cond(w);
double b = Number(w, "/=");
if(b == 0)
EscValue v = Get(r);
EscValue b = Get(w);
double q = Number(v, "/=");
if(q == 0)
ThrowError("divide by zero");
Assign(r, Number(r, "/=") / b);
Assign(r, Number(b, "/=") / q);
}
else
if(Char2('%', '=')) {
SRVal w;
Cond(w);
double b = Number(w, "%=");
int64 a = Int(r, "%=");
int64 b = Int(w, "%=");
if(b == 0)
ThrowError("divide by zero");
Assign(r, Number(r, "%=") / b);
Assign(r, a % b);
}
}
@ -1042,7 +1097,7 @@ void Esc::DoStatement()
if(range.IsArray()) {
if(i >= range.GetCount())
break;
Assign(var, i);
Assign(var, (int64)i);
}
else
if(range.IsMap()) {

View file

@ -6,7 +6,7 @@
NAMESPACE_UPP
enum { ESC_VOID, ESC_NUMBER, ESC_ARRAY, ESC_MAP, ESC_LAMBDA };
enum { ESC_VOID, ESC_DOUBLE, ESC_ARRAY, ESC_MAP, ESC_LAMBDA, ESC_INT64 };
String EscTypeName(int sv_type);
@ -29,6 +29,7 @@ class EscValue : Moveable<EscValue> {
union {
double number;
int64 i64;
EscArray *array;
EscMap *map;
EscLambda *lambda;
@ -53,11 +54,15 @@ public:
bool IsVoid() const { return type == ESC_VOID; }
EscValue();
bool IsNumber() const { return type == ESC_NUMBER; }
double GetNumber() const { return IsNumber() ? number : 0; }
bool IsNumber() const { return findarg(type, ESC_DOUBLE, ESC_INT64) >= 0; }
double GetNumber() const;
bool IsInt64() const { return type == ESC_INT64; }
int64 GetInt64() const;
bool IsInt() const;
int GetInt() const;
EscValue(double n);
EscValue(int64 n);
EscValue(int n);
bool IsArray() const { return type == ESC_ARRAY; }
const Vector<EscValue>& GetArray() const;
@ -184,6 +189,9 @@ struct Esc : public CParser {
SRVal() { lval = NULL; }
SRVal(const EscValue& v) { lval = NULL; rval = v; }
SRVal(double n) { lval = NULL; rval = n; }
SRVal(int64 n) { lval = NULL; rval = n; }
SRVal(uint64 n) { lval = NULL; rval = (int64)n; }
SRVal(bool n) { lval = NULL; rval = (int64)n; }
};
ArrayMap<String, EscValue>& global;
@ -215,9 +223,9 @@ struct Esc : public CParser {
EscValue GetExp();
double Number(const EscValue& a, const char *oper);
int Int(const EscValue& a, const char *oper);
int64 Int(const EscValue& a, const char *oper);
double Number(const SRVal& a, const char *oper);
int Int(const SRVal& a, const char *oper);
int64 Int(const SRVal& a, const char *oper);
EscValue MulArray(EscValue array, EscValue times);

View file

@ -117,7 +117,7 @@ void EscValue::InitString(const WString& s)
Vector<EscValue>& a = array->array;
a.SetCount(s.GetCount());
for(int i = 0; i < s.GetCount(); i++)
a[i] = s[i];
a[i] = (int64)s[i];
total++;
}
@ -144,7 +144,23 @@ EscValue::EscValue()
EscValue::EscValue(double n)
{
number = n;
type = ESC_NUMBER;
type = ESC_DOUBLE;
hash = 0;
total++;
}
EscValue::EscValue(int64 n)
{
i64 = n;
type = ESC_INT64;
hash = 0;
total++;
}
EscValue::EscValue(int n)
{
i64 = n;
type = ESC_INT64;
hash = 0;
total++;
}

View file

@ -100,7 +100,7 @@ int EscEscape::Int(int i)
{
if(i >= arg.GetCount())
ThrowError("too little parameters" + InCall());
return esc.Int(arg[i], "parameter" + InCall());
return (int)esc.Int(arg[i], "parameter" + InCall());
}
void EscEscape::CheckArray(int i)

View file

@ -46,7 +46,10 @@ void ESC_to_number(EscEscape& e)
if(e[0].IsArray()) {
double d = ScanDouble((String)e[0]);
if(!IsNull(d))
e = d;
if(d <= INT64_MAX && d >= INT64_MIN)
e = ScanInt64((String)e[0]);
else
e = d;
}
}

View file

@ -10,7 +10,8 @@ String EscTypeName(int sv_type)
switch(sv_type)
{
case ESC_VOID: return "void";
case ESC_NUMBER: return "number";
case ESC_DOUBLE: return "double";
case ESC_INT64: return "int64";
case ESC_ARRAY: return "array";
case ESC_MAP: return "map";
case ESC_LAMBDA: return "lambda";
@ -59,9 +60,12 @@ void EscValue::Assign(const EscValue& s)
lambda = s.lambda;
lambda->Retain();
break;
case ESC_NUMBER:
case ESC_DOUBLE:
number = s.number;
break;
case ESC_INT64:
i64 = s.i64;
break;
}
}
@ -116,9 +120,12 @@ unsigned EscValue::GetHashValue() const
case ESC_VOID:
hash = 1;
break;
case ESC_NUMBER:
case ESC_DOUBLE:
hash = UPP::GetHashValue(number) | 0x80000;
break;
case ESC_INT64:
hash = UPP::GetHashValue(i64) | 0x80000;
break;
case ESC_ARRAY:
for(int i = 0; i < array->array.GetCount(); i++)
hash = hash ^ array->array[i].GetHashValue();
@ -156,8 +163,11 @@ bool EscValue::operator==(const EscValue& a) const
switch(type) {
case ESC_VOID:
return a.type == ESC_VOID;
case ESC_NUMBER:
return a.type == ESC_NUMBER && number == a.number;
case ESC_INT64:
if(a.type == ESC_INT64)
return i64 == a.i64;
case ESC_DOUBLE:
return a.IsNumber() && GetNumber() == a.GetNumber();
case ESC_ARRAY:
if(a.type != ESC_ARRAY) return false;
if(array->array.GetCount() != a.array->array.GetCount())
@ -195,7 +205,7 @@ String EscValue::ToString(int maxlen, int indent_step, bool hex, int indent) con
String s;
int i;
switch(type) {
case ESC_NUMBER:
case ESC_DOUBLE:
{
s = ind;
if((int64)number == number)
@ -208,6 +218,16 @@ String EscValue::ToString(int maxlen, int indent_step, bool hex, int indent) con
s << ' ' << AsCString(ToUtf8(WString((int)number, 1)));
return s;
}
case ESC_INT64:
{
s = ind;
s << FormatInt64(i64);
if(hex)
s << " 0x" << Format64Hex(i64);
if(hex && i64 >= 0 && i64 < 65536)
s << ' ' << AsCString(ToUtf8(WString((int)i64, 1)));
return s;
}
case ESC_ARRAY:
{
const Vector<EscValue>& a = GetArray();
@ -298,14 +318,36 @@ String EscValue::ToString(int maxlen, int indent_step, bool hex, int indent) con
return "void";
}
bool EscValue::IsInt() const
double EscValue::GetNumber() const
{
return IsNumber() && number >= (double)INT_MIN && number <= (double)INT_MAX;
if(type == ESC_INT64)
return (double)i64;
if(type == ESC_DOUBLE)
return number;
return 0;
}
int EscValue::GetInt() const
int64 EscValue::GetInt64() const
{
return (int)minmax(GetNumber(), (double)INT_MIN, (double)INT_MAX);
if(type == ESC_INT64)
return i64;
if(type == ESC_DOUBLE && number >= (double)INT64_MIN && number <= (double)INT64_MAX)
return (int64)number;
return 0;
}
bool EscValue::IsInt() const
{
if(IsInt64()) {
int64 n = GetInt64();
return n >= INT_MIN && n <= INT_MAX;
}
return false;
}
int EscValue::GetInt() const
{
return IsInt() ? (int)GetInt64() : 0;
}
bool IsTrue(const EscValue& a)