From b417b9443bed15dd3634bebbb08352829693857b Mon Sep 17 00:00:00 2001 From: cxl Date: Sun, 14 Sep 2014 08:35:07 +0000 Subject: [PATCH] Esc now supports int64 git-svn-id: svn://ultimatepp.org/upp/trunk@7686 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/Esc/Esc.cpp | 139 +++++++++++++++++++++++++++------------ uppsrc/Esc/Esc.h | 18 +++-- uppsrc/Esc/EscArray.cpp | 20 +++++- uppsrc/Esc/EscRun.cpp | 2 +- uppsrc/Esc/EscStdLib.cpp | 5 +- uppsrc/Esc/EscValue.cpp | 62 ++++++++++++++--- 6 files changed, 185 insertions(+), 61 deletions(-) diff --git a/uppsrc/Esc/Esc.cpp b/uppsrc/Esc/Esc.cpp index 0f9123709..fa5c93f0c 100644 --- a/uppsrc/Esc/Esc.cpp +++ b/uppsrc/Esc/Esc.cpp @@ -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& 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& 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& 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& x = a.GetArray(); const Vector& 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()) { diff --git a/uppsrc/Esc/Esc.h b/uppsrc/Esc/Esc.h index 26965f8a0..6445f716f 100644 --- a/uppsrc/Esc/Esc.h +++ b/uppsrc/Esc/Esc.h @@ -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 { 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& 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& 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); diff --git a/uppsrc/Esc/EscArray.cpp b/uppsrc/Esc/EscArray.cpp index 689c25b80..4e473d66e 100644 --- a/uppsrc/Esc/EscArray.cpp +++ b/uppsrc/Esc/EscArray.cpp @@ -117,7 +117,7 @@ void EscValue::InitString(const WString& s) Vector& 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++; } diff --git a/uppsrc/Esc/EscRun.cpp b/uppsrc/Esc/EscRun.cpp index fa0185917..bb972c657 100644 --- a/uppsrc/Esc/EscRun.cpp +++ b/uppsrc/Esc/EscRun.cpp @@ -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) diff --git a/uppsrc/Esc/EscStdLib.cpp b/uppsrc/Esc/EscStdLib.cpp index e1ae5407a..460f7aa75 100644 --- a/uppsrc/Esc/EscStdLib.cpp +++ b/uppsrc/Esc/EscStdLib.cpp @@ -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; } } diff --git a/uppsrc/Esc/EscValue.cpp b/uppsrc/Esc/EscValue.cpp index fa674685c..a00d52d0a 100644 --- a/uppsrc/Esc/EscValue.cpp +++ b/uppsrc/Esc/EscValue.cpp @@ -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& 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)