Ide/Debuggers/Gdb_MI2 : completed type evaluators for string, vector and corresponding maps

git-svn-id: svn://ultimatepp.org/upp/trunk@6913 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
micio 2014-02-13 00:27:14 +00:00
parent 0fb78efebf
commit 2b09abdfa7
10 changed files with 636 additions and 232 deletions

View file

@ -11,7 +11,9 @@ file
Gdb.lay,
MIValue.h,
MIValue.cpp,
TypeSimplify.h,
TypeSimplify.cpp,
UppSimplifiers.icpp,
VarItem.cpp,
Terminal.cpp,
Disas.cpp,
@ -19,6 +21,7 @@ file
Gdb.cpp,
Gdb_MI2.lay,
Gdb_MI2.h,
Gdb_MI2Eval.cpp,
Gdb_MI2.cpp,
PrettyPrinters.brc,
PrettyPrinters.py,

View file

@ -11,7 +11,7 @@ static VectorMap<String, String> DataMap2(const ArrayCtrl& data)
{
VectorMap<String, String> m;
for(int i = 0; i < data.GetCount(); i++)
m.Add(data.Get(i, 0), data.Get(i, 2));
m.Add(data.Get(i, 0), data.Get(i, 1));
return m;
}
@ -20,10 +20,10 @@ static void MarkChanged2(const VectorMap<String, String>& m, ArrayCtrl& data)
for(int i = 0; i < data.GetCount(); i++)
{
int q = m.Find(data.Get(i, 0));
if(q >= 0 && m[q] != data.Get(i, 2))
data.SetDisplay(i, 2, Single<RedDisplay>());
if(q >= 0 && m[q] != data.Get(i, 1))
data.SetDisplay(i, 1, Single<RedDisplay>());
else
data.SetDisplay(i, 2, StdDisplay());
data.SetDisplay(i, 1, StdDisplay());
}
}
@ -1108,145 +1108,11 @@ void Gdb_MI2::UpdateLocalVars(void)
}
}
// deeply explore a value
// taking its members and skipping types
// WARNING, it APPENDS results to given arrays
void Gdb_MI2::ExploreValueDeep(String baseName, MIValue const &val, Vector<String> &fullNames, Vector<String> &values) const
{
// if value is a string, just append baseName and value to result
if(val.IsString())
{
fullNames.Add(baseName);
values.Add(val.ToString());
}
// otherwise, if value is a tuple, recursively add all subvalues
else if(val.IsTuple())
{
for(int iVal = 0; iVal < val.GetCount(); iVal++)
{
String name = val.GetKey(iVal);
if(!name.StartsWith("<"))
name = baseName + '.' + name;
else
name = baseName;
ExploreValueDeep(name, val.Get(iVal), fullNames, values);
}
}
}
// update 'this' inspector data
void Gdb_MI2::UpdateThis(void)
{
/*
thisNames.Clear();
thisExpressions.Clear();
thisValues.Clear();
VarItem v = EvalGdb("*this");
v.shortExpression = ".";
thisNames.Add(v.shortExpression);
thisExpressions.Add(v.evaluableExpression);
thisValues.Add(v.value);
Vector<VarItem> vv;
if(v.kind == VarItem::SIMPLE)
vv = GetChildren(v);
else
vv = GetChildren(v, 0, 10);
for(int iChild = 0; iChild < vv.GetCount(); iChild++)
{
VarItem &v = vv[iChild];
thisNames.Add(v.shortExpression);
thisExpressions.Add(v.evaluableExpression);
thisValues.Add(v.value);
}
*/
thisNames.Clear();
thisExpressions.Clear();
thisValues.Clear();
Vector<String>names, values;
MIValue thisVal = MICmd("data-evaluate-expression *this");
if(!thisVal.IsTuple())
return;
if(thisVal.Find("value") >= 0)
{
// weird but the value is quoted, so must be parsed again...
MIValue const &tup = thisVal.Get("value");
if(!tup.IsString())
return;
MIValue s(tup.ToString());
s.PackNames();
//RLOG(s.Dump());
TypeSimplify(s);
ExploreValueDeep("", s, names, values);
}
else if(thisVal.Find("variables") >= 0)
{
MIValue &arr = thisVal.Get("variables");
if(!arr.IsArray())
return;
for(int iVal = 0; iVal < arr.GetCount(); iVal++)
{
MIValue &val = arr[iVal];
if(!val.IsTuple() || val.Find("name") < 0 || val.Find("value") < 0)
continue;
MIValue &s = val.Get("value");
s.PackNames();
TypeSimplify(s);
val.PackNames();
ExploreValueDeep("." + val.Get("name").ToString(), s, thisExpressions, thisValues);
}
}
// build short names from full names
for(int iName = 0; iName < thisExpressions.GetCount(); iName++)
{
String const &nam = thisExpressions[iName];
String shortName;
int pos = nam.ReverseFind('.');
if(pos < 0)
shortName = nam;
else
shortName = nam.Mid(pos + 1);
thisNames.Add(shortName);
}
// here the 'this' object is dumped inside the 2 vectors 'names' and 'values'
// we need to do some cleanup, removing empty values, class names and so on
// we shall also construct the 'thisNames' vector containing just the last name path
// used for tooltip
for(int iName = 0; iName < names.GetCount(); iName++)
{
String const &name = names[iName];
if(name.IsEmpty())
continue;
if(name == "<No data fields>")
continue;
if(name.StartsWith("_vptr."))
continue;
String const &val = values[iName];
if(val.IsEmpty())
continue;
String shortName;
int dotPos = name.ReverseFind('.');
if(dotPos < 0)
shortName = name;
else
shortName = name.Mid(dotPos + 1);
thisNames.Add(shortName);
thisExpressions.Add(name);
thisValues.Add(val);
}
MIValue val = Evaluate("*this");
CollectVariables(val, thisExpressions, thisValues, thisHints);
}
// sync auto vars treectrl
@ -1299,8 +1165,8 @@ void Gdb_MI2::SyncMembers(void)
VectorMap<String, String> prev = DataMap2(members);
members.Clear();
for(int iMem = 0; iMem < thisNames.GetCount(); iMem++)
members.Add(thisExpressions[iMem], thisValues[iMem]);
for(int iMem = 0; iMem < thisExpressions.GetCount(); iMem++)
members.Add(thisExpressions[iMem].Mid(7), thisValues[iMem]);
MarkChanged2(prev, members);
}
@ -1639,6 +1505,12 @@ void Gdb_MI2::onExploreExpr(ArrayCtrl *what)
// we use the expression editbox
expr = ~explorerExprEdit;
}
else if(what == &members)
{
int line = what->GetCursor();
if(line >= 0)
expr = thisExpressions[line];
}
else
{
// otherwise, we use the expression from sending ArrayCtrl

View file

@ -170,9 +170,9 @@ class Gdb_MI2 : public Debugger, public ParentCtrl
Vector<String>watchesValues;
// 'this' variable inspection data
Index<String>thisNames;
Vector<String>thisExpressions;
Vector<String>thisValues;
Vector<int>thisHints;
// stored autos expressions, values and types
String autoLine;
@ -180,18 +180,7 @@ class Gdb_MI2 : public Debugger, public ParentCtrl
// update local variables on demand
void UpdateLocalVars(void);
// deeply explore a value
// taking its members and skipping types
// WARNING, it APPENDS results to given arrays
void ExploreValueDeep(String baseName, MIValue const &val, Vector<String> &fullNames, Vector<String> &values) const;
// known types simplifier
// takes a MIValue from '-data-evaluate-expression' command and try
// do simplify diplay of known types
void TypeSimplify(MIValue &val);
// update 'this' inspector data
void UpdateThisDeep(VarItem &v);
void UpdateThis(void);
// logs frame data on console
@ -285,6 +274,16 @@ class Gdb_MI2 : public Debugger, public ParentCtrl
String GetHostPath(const String& path) { return host->GetHostPath(path); }
String GetLocalPath(const String& path) { return host->GetLocalPath(path); }
// known types simplifier
// takes a MIValue from '-data-evaluate-expression' command and try
// do simplify diplay of known types
void TypeSimplify(MIValue &val);
// collects evaluated variables got with Evaluate
// hints are used to choose the visualizer when deep-inspecting members
// 0 for simple values, 1 for arrays, 2 for map
void CollectVariables(MIValue &val, Vector<String> &exprs, Vector<String> &vals, Vector<int> &hints);
protected:
public :
@ -306,6 +305,13 @@ class Gdb_MI2 : public Debugger, public ParentCtrl
Gdb_MI2();
virtual ~Gdb_MI2();
// variable inspection support
// returns a MIValue with inspected data and some info fields added
// and known types simplified and cathegorized
// unknown and simple types are left as they are
MIValue Evaluate(String expr);
};
#endif

View file

@ -0,0 +1,182 @@
#include "Debuggers.h"
#include <ide/ide.h>
#include "TypeSimplify.h"
// now we scan the result and add some info
// so, for example, if we find tuple like this one:
// data = simplevalue
// this will be modified as
// data = { value = simplevalue, expr = evaluable_expression }
// and for a complex value
// data = { some=complex, not_simple=val }
// woll be modified as
// data = { <!value> = { some=complex, not_simple=val }, <!expr> = evaluable_expression }
// More attributes will be added by type simplifier phase
static void AddAttribs(String const &expr, MIValue &valExpr)
{
if(valExpr.IsTuple())
{
for(int i = 0; i < valExpr.GetCount(); i++)
{
String nam = valExpr.GetKey(i);
String nExpr;
if(!nam.StartsWith("<"))
nExpr = expr + "." + nam;
else
nExpr = expr;
MIValue v = valExpr[i];
valExpr[i].Clear();
valExpr[i].Add(SIMPLIFY_VALUE, v);
valExpr[i].Add(SIMPLIFY_EXPR, nExpr);
AddAttribs(nExpr, valExpr[i][SIMPLIFY_VALUE]);
}
}
else if(valExpr.IsArray())
{
}
}
void Gdb_MI2::TypeSimplify(MIValue &val)
{
if(val.IsTuple())
{
for(int i = 0; i < val.GetCount(); i++)
{
// root of variable -- contains VALUE, EXPRESSION and will add HINTS
MIValue &vRoot = val[i];
// value part of variable
MIValue &v = vRoot[SIMPLIFY_VALUE];
if(v.IsTuple() && v.GetCount())
{
String key = v.GetKey(0);
if(key.StartsWith("<!"))
continue;
if(key.StartsWith("<"))
{
TYPE_SIMPLIFIER_HANDLER handler = GetSimplifier(v.GetKey(0));
if(handler)
handler(*this, vRoot);
else
TypeSimplify(v);
}
else
TypeSimplify(v);
}
else
TypeSimplify(v);
}
}
}
// variable inspection support
// returns a MIValue with inspected data and some info fields added
// and known types simplified and cathegorized
// unknown and simple types are left as they are
MIValue Gdb_MI2::Evaluate(String expr)
{
// add parhentesis around expression... gdb is dumb
expr = "(" + expr + ")";
// ask gdb to evaluate expression
// and gather result in a tuple
MIValue valExpr = MICmd("data-evaluate-expression " + expr);
// return empty value on error
if(!valExpr.IsTuple())
return MIValue();
if(valExpr.Find("value") >= 0)
{
// weird but the value is quoted, so must be parsed again...
MIValue const &tup = valExpr.Get("value");
if(!tup.IsString())
return MIValue();
String s = tup.ToString();
MIValue parsed(s);
// enclose it in a dummy container
MIValue enclosed;
enclosed.Add("<DUMMY>", parsed);
// remove spaces from names
enclosed.PackNames();
// Add attributes to expression data
AddAttribs(expr, enclosed);
// now we go through the type simplifier, which try to give simple representation
// for known types
TypeSimplify(enclosed);
//RLOG(enclosed.Dump());
// now we can de-enclose it...
parsed = enclosed["<DUMMY>"][SIMPLIFY_VALUE];
//RLOG(parsed.Dump());
// and finally return the cleaned evaluated data
return parsed;
}
else if(valExpr.Find("variables") >= 0)
{
RLOG("ARRAY SIDE UNHANDLED....");
return MIValue();
}
else
{
RLOG("WEIRD STUFF HERE....");
return MIValue();
}
}
// collects evaluated variables got with Evaluate
// hints are used to choose the visualizer when deep-inspecting members
// 0 for simple values, 1 for arrays, 2 for map
static void Collect0(MIValue &val, Vector<String> &exprs, Vector<String> &vals, Vector<int> &hints)
{
if(!val.IsTuple())
return;
for(int i = 0; i < val.GetCount(); i++)
{
MIValue &v = val[i];
MIValue &data = v[SIMPLIFY_VALUE];
if(data.IsError())
continue;
if(data.IsString())
{
String d = data.ToString();
if(!d.StartsWith("<"))
{
vals.Add(data.ToString()),
exprs.Add(v[SIMPLIFY_EXPR]);
String hint = v.Get(SIMPLIFY_HINT, SIMPLIFY_SIMPLE);
if(hint == SIMPLIFY_SIMPLE)
hints << 0;
else if(hint == SIMPLIFY_ARRAY)
hints << 1;
else if(hint == SIMPLIFY_MAP)
hints << 2;
else
hints << 0;
}
}
else if(data.IsTuple())
Collect0(data, exprs, vals, hints);
}
}
void Gdb_MI2::CollectVariables(MIValue &val, Vector<String> &exprs, Vector<String> &vals, Vector<int> &hints)
{
exprs.Clear();
vals.Clear();
hints.Clear();
Collect0(val, exprs, vals, hints);
}

View file

@ -245,7 +245,7 @@ int MIValue::ParseAngle(String const &s, int i)
}
i++;
}
if(!expect("ParseAngle", '"', i-1, s))
if(!expect("ParseAngle", '>', i-1, s))
return s.GetCount();
string.Cat('>');
@ -638,3 +638,64 @@ void MIValue::PackNames(void)
array[i].PackNames();
}
}
// add an item to a tuple
MIValue &MIValue::Add(String const &key, MIValue pick_ &v)
{
if(IsEmpty())
{
Clear();
type = MITuple;
}
if(type != MITuple)
return ErrorMIValue("Not a Tuple value type");
tuple.AddPick(key, v);
return *this;
}
MIValue &MIValue::Add(String const &key, String const &data)
{
MIValue v;
v.Set(data);
return Add(key, v);
}
MIValue &MIValue::FindAdd(String const &key, String const &data)
{
if(IsEmpty())
{
Clear();
type = MITuple;
}
if(type != MITuple)
return ErrorMIValue("Not a Tuple value type");
int idx = tuple.Find(key);
MIValue v;
v.Set(data);
if(idx >= 0)
tuple[idx] = v;
else
tuple.AddPick(key, v);
return *this;
}
// add an item to an array
MIValue &MIValue::Add(MIValue pick_ &v)
{
if(IsEmpty())
{
Clear();
type = MIArray;
}
if(type != MIArray)
return ErrorMIValue("Not a Array value type");
array.AddPick(v);
return *this;
}
MIValue &MIValue::Add(String const &data)
{
MIValue v;
v.Set(data);
return Add(v);
}

View file

@ -96,6 +96,17 @@ class MIValue : public Moveable<MIValue>
// packs names inside tuples -- to make type recognition easy
void PackNames(void);
// add some data to a value
// add an item to a tuple
MIValue &Add(String const &key, MIValue pick_ &v);
MIValue &Add(String const &key, String const &data);
MIValue &FindAdd(String const &key, String const &data);
// add an item to an array
MIValue &Add(MIValue pick_ &v);
MIValue &Add(String const &data);
};
#endif

View file

@ -1,86 +1,23 @@
#include "Debuggers.h"
#include <ide/ide.h>
#include "TypeSimplify.h"
typedef bool (*TYPE_SIMPLIFIER_HANDLER)(MIValue &val);
static bool UppStringSimplify(MIValue &val)
static VectorMap<String, TYPE_SIMPLIFIER_HANDLER> &GetSimplifierMap(void)
{
// strings are "easy", in debug mode 's' and 'len' members are provided
// so we shall just look at them in tuple
// see Upp::String code for how it works....
try
{
MIValue &v = val[0][0][0];
MIValue &unn = v[1];
if(!v.IsTuple() || !unn.IsTuple())
return false;
if(unn.Find("chr") < 0)
return false;
String chr = unn["chr"];
bool isSmall = (chr[14] == 0);
String s;
if(isSmall)
s = chr;
else
{
if(unn.Find("ptr") < 0)
return false;
s = unn["ptr"];
// strip address...
int i = s.Find('"');
if(i >= 0)
{
s = s.Mid(i+1);
s = s.Left(s.GetCount()-1);
}
}
val.Set(s);
return true;
}
catch(...)
{
return false;
}
static VectorMap<String, TYPE_SIMPLIFIER_HANDLER> map;
return map;
}
struct TYPE_SIMPLIFIER
void RegisterSimplifier(const char *pattern, TYPE_SIMPLIFIER_HANDLER handler)
{
const char *type;
TYPE_SIMPLIFIER_HANDLER handler;
GetSimplifierMap().Add(pattern, handler);
}
};
TYPE_SIMPLIFIER TYPE_SIMPLIFIERS[] =
TYPE_SIMPLIFIER_HANDLER GetSimplifier(String const &pattern)
{
{ "<Upp::Moveable<Upp::String,Upp::AString<Upp::String0>>>", UppStringSimplify }
};
#define SIMPLIFIERS_COUNT ((int)(sizeof(TYPE_SIMPLIFIERS) / sizeof(TYPE_SIMPLIFIER)))
void Gdb_MI2::TypeSimplify(MIValue &val)
{
static VectorMap<String, TYPE_SIMPLIFIER_HANDLER> handlers;
if(!handlers.GetCount())
for(int i = 0; i < SIMPLIFIERS_COUNT; i++)
handlers.Add(TYPE_SIMPLIFIERS[i].type, TYPE_SIMPLIFIERS[i].handler);
if(val.IsTuple())
VectorMap<String, TYPE_SIMPLIFIER_HANDLER> &map = GetSimplifierMap();
for(int i = 0; i < map.GetCount(); i++)
{
for(int i = 0; i < val.GetCount(); i++)
{
MIValue &v = val[i];
if(v.IsTuple() && v.GetCount())
{
int idx = handlers.Find(v.GetKey(0));
if(idx >= 0)
handlers[idx](v);
else
TypeSimplify(v);
}
else
TypeSimplify(v);
}
if(pattern.StartsWith(map.GetKey(i)))
return map[i];
}
}
return NULL;
}

View file

@ -0,0 +1,32 @@
#ifndef _ide_Debuggers_TypeSimplify_h_
#define _ide_Debuggers_TypeSimplify_h_
#include "Debuggers.h"
#include <ide/ide.h>
#define SIMPLIFY_EXPR "<!EXPR>"
#define SIMPLIFY_VALUE "<!VALUE>"
#define SIMPLIFY_HINT "<!HINT>"
#define SIMPLIFY_START "<!START>"
#define SIMPLIFY_COUNT "<!COUNT>"
#define SIMPLIFY_SIMPLE "<!SIMPLE>"
#define SIMPLIFY_ARRAY "<!ARRAY>"
#define SIMPLIFY_MAP "<!MAP>"
// Simplifier handler
// parameters:
// gdb handler to debugger object -- used mostly to inspect deeper
// expRoot gdb evaluable expression of 'val' expression root. The one used to get the 'val'.
typedef bool (*TYPE_SIMPLIFIER_HANDLER)(Gdb_MI2 &gdb, MIValue &val);
void RegisterSimplifier(const char *pattern, TYPE_SIMPLIFIER_HANDLER handler);
TYPE_SIMPLIFIER_HANDLER GetSimplifier(String const &pattern);
#define REGISTERSIMPLIFIER(pattern, handler) \
INITBLOCK { \
RegisterSimplifier(pattern, handler); \
}
#endif

View file

@ -0,0 +1,297 @@
#include "TypeSimplify.h"
static bool UppStringSimplify(Gdb_MI2 &gdb, MIValue &val)
{
// strings are "easy", in debug mode 's' and 'len' members are provided
// so we shall just look at them in tuple
// see Upp::String code for how it works....
try
{
MIValue &v = val[SIMPLIFY_VALUE][0][0][0][0][0][SIMPLIFY_VALUE];
MIValue &unn = v[1][SIMPLIFY_VALUE];
if(!v.IsTuple() || !unn.IsTuple())
return false;
if(unn.Find("chr") < 0)
return false;
String chr = unn["chr"][SIMPLIFY_VALUE];
bool isSmall = (chr[14] == 0);
String s;
if(isSmall)
s = chr;
else
{
if(unn.Find("ptr") < 0)
return false;
s = unn["ptr"][SIMPLIFY_VALUE];
// strip address...
int i = s.Find('"');
if(i >= 0)
{
s = s.Mid(i+1);
s = s.Left(s.GetCount()-1);
}
}
val[SIMPLIFY_VALUE].Set("\"" + s + "\"");
val.FindAdd(SIMPLIFY_HINT, SIMPLIFY_SIMPLE);
return true;
}
catch(...)
{
return false;
}
}
static bool UppVectorSimplify(Gdb_MI2 &gdb, MIValue &val)
{
//RLOG(val.Dump());
try
{
MIValue &v = val[SIMPLIFY_VALUE];
String vectorExpr = v["vector"][SIMPLIFY_EXPR];
int items = atoi(v["items"][SIMPLIFY_VALUE].ToString());
val.FindAdd(SIMPLIFY_HINT, SIMPLIFY_ARRAY);
val.FindAdd(SIMPLIFY_START, "0");
val.FindAdd(SIMPLIFY_COUNT, FormatInt(items));
// display max 5 elements of array, starting from 0 and ONLY if elements evaluate to a simple type
// otherwise display {...} string
// to do this, we shall ask gdb to evaluate the undelying vector
int count = min(5, items);
String vals = "";
for(int i = 0; i < count; i++)
{
MIValue vi = gdb.Evaluate(vectorExpr + Format("[%d]", i));
if(vi.IsError())
{
vals = "can't evaluate";
break;
}
if(!vi.IsString())
{
vals = "{...}";
break;
}
vals = vals + ", " + vi.ToString();
}
if(vals.StartsWith(", "))
vals = vals.Mid(2);
vals = Format("Upp::Vector with %d elements : %s", items, vals);
//RLOG("VALS = " << vals);
val[SIMPLIFY_VALUE].Set(vals);
//RLOG(v.Dump());
return true;
}
catch(...)
{
return false;
}
}
static bool UppVectorMapSimplify(Gdb_MI2 &gdb, MIValue &val)
{
//RLOG(val.Dump());
try
{
MIValue &v = val[SIMPLIFY_VALUE];
MIValue &keyPtr = v[1][0]["key"][0][1][0][0][0];
String keyExpr = keyPtr["vector"][SIMPLIFY_EXPR].ToString();
int items = atoi(keyPtr["items"][SIMPLIFY_VALUE].ToString());
MIValue &valPtr = v[1][0]["value"][SIMPLIFY_VALUE];;
String valExpr = valPtr["vector"][SIMPLIFY_EXPR].ToString();
val.FindAdd(SIMPLIFY_HINT, SIMPLIFY_MAP);
val.FindAdd(SIMPLIFY_START, "0");
val.FindAdd(SIMPLIFY_COUNT, FormatInt(items));
// display max 3 elements of map, starting from 0 and ONLY if elements evaluate to a simple type
// otherwise display {...} string
// to do this, we shall ask gdb to evaluate the undelying vector
int count = min(3, items);
String vals = "";
bool err = false;
bool complex = false;
for(int i = 0; i < count; i++)
{
MIValue vk = gdb.Evaluate(keyExpr + Format("[%d]", i));
if(vk.IsError())
{
err = true;
break;
}
if(!vk.IsString())
{
complex = true;
break;
}
MIValue vv = gdb.Evaluate(valExpr + Format("[%d]", i));
if(vv.IsError())
{
err = true;
break;
}
if(!vv.IsString())
{
complex = true;
break;
}
vals = vals + ", (" + vk.ToString() + "," + vv.ToString() + ")";
}
if(complex)
vals = "{...}";
else if(err)
vals = "can't evaluate";
if(vals.StartsWith(", "))
vals = vals.Mid(2);
vals = Format("Upp::VectorMap with %d elements : %s", items, vals);
//RLOG("VALS = " << vals);
val[SIMPLIFY_VALUE].Set(vals);
return true;
}
catch(...)
{
return false;
}
}
static bool UppArraySimplify(Gdb_MI2 &gdb, MIValue &val)
{
//RLOG(val.Dump());
try
{
MIValue &v = val[SIMPLIFY_VALUE]["vector"][SIMPLIFY_VALUE];
String vectorExpr = v["vector"][SIMPLIFY_EXPR];
int items = atoi(v["items"][SIMPLIFY_VALUE].ToString());
val.FindAdd(SIMPLIFY_HINT, SIMPLIFY_ARRAY);
val.FindAdd(SIMPLIFY_START, "0");
val.FindAdd(SIMPLIFY_COUNT, FormatInt(items));
// display max 5 elements of array, starting from 0 and ONLY if elements evaluate to a simple type
// otherwise display {...} string
// to do this, we shall ask gdb to evaluate the undelying vector
int count = min(5, items);
String vals = "";
for(int i = 0; i < count; i++)
{
MIValue vi = gdb.Evaluate(vectorExpr + Format("[%d][0]", i));
if(vi.IsError())
{
vals = "can't evaluate";
break;
}
if(!vi.IsString())
{
vals = "{...}";
break;
}
vals = vals + ", " + vi.ToString();
}
if(vals.StartsWith(", "))
vals = vals.Mid(2);
vals = Format("Upp::Array with %d elements : %s", items, vals);
//RLOG("VALS = " << vals);
val[SIMPLIFY_VALUE].Set(vals);
//RLOG(v.Dump());
return true;
}
catch(...)
{
return false;
}
}
static bool UppArrayMapSimplify(Gdb_MI2 &gdb, MIValue &val)
{
//RLOG(val.Dump());
try
{
MIValue &v = val[SIMPLIFY_VALUE];
MIValue &keyPtr = v[1][0]["key"][0][1][0][0][0];
String keyExpr = keyPtr["vector"][SIMPLIFY_EXPR].ToString();
int items = atoi(keyPtr["items"][SIMPLIFY_VALUE].ToString());
MIValue &valPtr = v[1][0]["value"][SIMPLIFY_VALUE];;
String valExpr = valPtr["vector"][SIMPLIFY_VALUE]["vector"][SIMPLIFY_EXPR].ToString();
val.FindAdd(SIMPLIFY_HINT, SIMPLIFY_MAP);
val.FindAdd(SIMPLIFY_START, "0");
val.FindAdd(SIMPLIFY_COUNT, FormatInt(items));
// display max 3 elements of map, starting from 0 and ONLY if elements evaluate to a simple type
// otherwise display {...} string
// to do this, we shall ask gdb to evaluate the undelying vector
int count = min(3, items);
String vals = "";
bool err = false;
bool complex = false;
for(int i = 0; i < count; i++)
{
MIValue vk = gdb.Evaluate(keyExpr + Format("[%d]", i));
if(vk.IsError())
{
err = true;
break;
}
if(!vk.IsString())
{
complex = true;
break;
}
MIValue vv = gdb.Evaluate(valExpr + Format("[%d][0]", i));
if(vv.IsError())
{
err = true;
break;
}
if(!vv.IsString())
{
complex = true;
break;
}
vals = vals + ", (" + vk.ToString() + "," + vv.ToString() + ")";
}
if(complex)
vals = "{...}";
else if(err)
vals = "can't evaluate";
if(vals.StartsWith(", "))
vals = vals.Mid(2);
vals = Format("Upp::ArrayMap with %d elements : %s", items, vals);
//RLOG("VALS = " << vals);
val[SIMPLIFY_VALUE].Set(vals);
return true;
}
catch(...)
{
return false;
}
}
// Register the simplifiers
REGISTERSIMPLIFIER("<Upp::Moveable<Upp::String,Upp::AString<Upp::String0>>>" , UppStringSimplify);
REGISTERSIMPLIFIER("<Upp::MoveableAndDeepCopyOption<Upp::Vector<" , UppVectorSimplify);
REGISTERSIMPLIFIER("<Upp::MoveableAndDeepCopyOption<Upp::VectorMap<" , UppVectorMapSimplify);
REGISTERSIMPLIFIER("<Upp::MoveableAndDeepCopyOption<Upp::Array<" , UppArraySimplify);
REGISTERSIMPLIFIER("<Upp::MoveableAndDeepCopyOption<Upp::ArrayMap<" , UppArrayMapSimplify);

View file

@ -3,4 +3,7 @@
#include "ide\Common/init"
#include "plugin\ndisasm/init"
#include "HexView/init"
#define BLITZ_INDEX__ Fa2117e771964dad617cdd6a1792596ea
#include "UppSimplifiers.icpp"
#undef BLITZ_INDEX__
#endif