Skip to content

Commit

Permalink
Merge pull request #5133 from WalterBright/delegate_speller
Browse files Browse the repository at this point in the history
refactor: speller from C++ fp to D delegate
  • Loading branch information
9rnsr committed Sep 28, 2015
2 parents a3f7a55 + 7d7f4b4 commit 7475ba9
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 118 deletions.
73 changes: 37 additions & 36 deletions src/dscope.d
Original file line number Diff line number Diff line change
Expand Up @@ -79,41 +79,6 @@ extern (C++) bool mergeFieldInit(Loc loc, ref uint fieldInit, uint fi, bool must
return true;
}

/************************************************
* Given the failed search attempt, try to find
* one with a close spelling.
*/
extern (C++) void* scope_search_fp(void* arg, const(char)* seed, int* cost)
{
//printf("scope_search_fp('%s')\n", seed);
/* If not in the lexer's string table, it certainly isn't in the symbol table.
* Doing this first is a lot faster.
*/
size_t len = strlen(seed);
if (!len)
return null;
Identifier id = Identifier.lookup(seed, len);
if (!id)
return null;
Scope* sc = cast(Scope*)arg;
Module.clearCache();
Dsymbol scopesym = null;
Dsymbol s = sc.search(Loc(), id, &scopesym, IgnoreErrors);
if (s)
{
for (*cost = 0; sc; sc = sc.enclosing, (*cost)++)
if (sc.scopesym == scopesym)
break;
if (scopesym != s.parent)
{
(*cost)++; // got to the symbol through an import
if (s.prot().kind == PROTprivate)
return null;
}
}
return cast(void*)s;
}

enum CSXthis_ctor = 0x01; // called this()
enum CSXsuper_ctor = 0x02; // called super()
enum CSXthis = 0x04; // referenced this
Expand Down Expand Up @@ -491,7 +456,43 @@ struct Scope
{
if (global.gag)
return null; // don't do it for speculative compiles; too time consuming
return cast(Dsymbol)speller(ident.toChars(), &scope_search_fp, &this, idchars);

/************************************************
* Given the failed search attempt, try to find
* one with a close spelling.
*/
extern (D) void* scope_search_fp(const(char)* seed, ref int cost)
{
//printf("scope_search_fp('%s')\n", seed);
/* If not in the lexer's string table, it certainly isn't in the symbol table.
* Doing this first is a lot faster.
*/
size_t len = strlen(seed);
if (!len)
return null;
Identifier id = Identifier.lookup(seed, len);
if (!id)
return null;
Scope* sc = &this;
Module.clearCache();
Dsymbol scopesym = null;
Dsymbol s = sc.search(Loc(), id, &scopesym, IgnoreErrors);
if (s)
{
for (cost = 0; sc; sc = sc.enclosing, ++cost)
if (sc.scopesym == scopesym)
break;
if (scopesym != s.parent)
{
++cost; // got to the symbol through an import
if (s.prot().kind == PROTprivate)
return null;
}
}
return cast(void*)s;
}

return cast(Dsymbol)speller(ident.toChars(), &scope_search_fp, idchars);
}

extern (C++) Dsymbol insert(Dsymbol s)
Expand Down
42 changes: 21 additions & 21 deletions src/dsymbol.d
Original file line number Diff line number Diff line change
Expand Up @@ -614,9 +614,29 @@ public:

final Dsymbol search_correct(Identifier ident)
{
/***************************************************
* Search for symbol with correct spelling.
*/
extern (D) void* symbol_search_fp(const(char)* seed, ref int cost)
{
/* If not in the lexer's string table, it certainly isn't in the symbol table.
* Doing this first is a lot faster.
*/
size_t len = strlen(seed);
if (!len)
return null;
Identifier id = Identifier.lookup(seed, len);
if (!id)
return null;
cost = 0;
Dsymbol s = this;
Module.clearCache();
return cast(void*)s.search(Loc(), id, IgnoreErrors);
}

if (global.gag)
return null; // don't do it for speculative compiles; too time consuming
return cast(Dsymbol)speller(ident.toChars(), &symbol_search_fp, cast(void*)this, idchars);
return cast(Dsymbol)speller(ident.toChars(), &symbol_search_fp, idchars);
}

/***************************************
Expand Down Expand Up @@ -1159,26 +1179,6 @@ public:
}
}

/***************************************************
* Search for symbol with correct spelling.
*/
extern (C++) void* symbol_search_fp(void* arg, const(char)* seed, int* cost)
{
/* If not in the lexer's string table, it certainly isn't in the symbol table.
* Doing this first is a lot faster.
*/
size_t len = strlen(seed);
if (!len)
return null;
Identifier id = Identifier.lookup(seed, len);
if (!id)
return null;
*cost = 0;
Dsymbol s = cast(Dsymbol)arg;
Module.clearCache();
return cast(void*)s.search(Loc(), id, IgnoreErrors);
}

/***********************************************************
* Dsymbol that generates a scope
*/
Expand Down
2 changes: 1 addition & 1 deletion src/posix.mak
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ SRC = win32.mak posix.mak osmodel.mak aggregate.h aliasthis.h arraytypes.h \

ROOT_SRC = $(addprefix $(ROOT)/,aav.h array.h file.h filename.h \
longdouble.h newdelete.c object.h outbuffer.h port.h rmem.h \
root.h speller.h stringtable.h)
root.h stringtable.h)

GLUE_SRC = glue.c msc.c s2ir.c todt.c e2ir.c tocsym.c \
toobj.c tocvdebug.c toir.h toir.c \
Expand Down
68 changes: 36 additions & 32 deletions src/root/speller.d
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ module ddmd.root.speller;

import core.stdc.limits, core.stdc.stdlib, core.stdc.string;

extern (C++) alias fp_speller_t = void* function(void*, const(char)*, int*);
alias dg_speller_t = void* delegate(const(char)*, ref int);

extern (C++) __gshared const(char)* idchars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
__gshared const(char)* idchars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";

/**************************************************
* combine a new result from the spell checker to
Expand All @@ -28,7 +28,7 @@ extern (C++) __gshared const(char)* idchars = "abcdefghijklmnopqrstuvwxyzABCDEFG
* true if the cost is less or equal 0
* false otherwise
*/
extern (C++) bool combineSpellerResult(ref void* p, ref int cost, void* np, int ncost)
bool combineSpellerResult(ref void* p, ref int cost, void* np, int ncost)
{
if (np && ncost < cost)
{
Expand All @@ -40,7 +40,7 @@ extern (C++) bool combineSpellerResult(ref void* p, ref int cost, void* np, int
return false;
}

extern (C++) void* spellerY(const(char)* seed, size_t seedlen, fp_speller_t fp, void* fparg, const(char)* charset, size_t index, int* cost)
void* spellerY(const(char)* seed, size_t seedlen, dg_speller_t dg, const(char)* charset, size_t index, int* cost)
{
if (!seedlen)
return null;
Expand All @@ -64,7 +64,7 @@ extern (C++) void* spellerY(const(char)* seed, size_t seedlen, fp_speller_t fp,
{
memcpy(buf + index, seed + index + 1, seedlen - index);
assert(buf[seedlen - 1] == 0);
void* np = (*fp)(fparg, buf, &ncost);
void* np = dg(buf, ncost);
if (combineSpellerResult(p, *cost, np, ncost))
return p;
}
Expand All @@ -78,7 +78,7 @@ extern (C++) void* spellerY(const(char)* seed, size_t seedlen, fp_speller_t fp,
{
buf[index] = *s;
//printf("sub buf = '%s'\n", buf);
void* np = (*fp)(fparg, buf, &ncost);
void* np = dg(buf, ncost);
if (combineSpellerResult(p, *cost, np, ncost))
return p;
}
Expand All @@ -90,7 +90,7 @@ extern (C++) void* spellerY(const(char)* seed, size_t seedlen, fp_speller_t fp,
{
buf[index] = *s;
//printf("ins buf = '%s'\n", buf);
void* np = (*fp)(fparg, buf, &ncost);
void* np = dg(buf, ncost);
if (combineSpellerResult(p, *cost, np, ncost))
return p;
}
Expand All @@ -99,7 +99,7 @@ extern (C++) void* spellerY(const(char)* seed, size_t seedlen, fp_speller_t fp,
return p; // return "best" result
}

extern (C++) void* spellerX(const(char)* seed, size_t seedlen, fp_speller_t fp, void* fparg, const(char)* charset, int flag)
void* spellerX(const(char)* seed, size_t seedlen, dg_speller_t dg, const(char)* charset, int flag)
{
if (!seedlen)
return null;
Expand All @@ -121,9 +121,9 @@ extern (C++) void* spellerX(const(char)* seed, size_t seedlen, fp_speller_t fp,
{
//printf("del buf = '%s'\n", buf);
if (flag)
np = spellerY(buf, seedlen - 1, fp, fparg, charset, i, &ncost);
np = spellerY(buf, seedlen - 1, dg, charset, i, &ncost);
else
np = (*fp)(fparg, buf, &ncost);
np = dg(buf, ncost);
if (combineSpellerResult(p, cost, np, ncost))
return p;
buf[i] = seed[i];
Expand All @@ -138,7 +138,7 @@ extern (C++) void* spellerX(const(char)* seed, size_t seedlen, fp_speller_t fp,
buf[i] = seed[i + 1];
buf[i + 1] = seed[i];
//printf("tra buf = '%s'\n", buf);
if (combineSpellerResult(p, cost, (*fp)(fparg, buf, &ncost), ncost))
if (combineSpellerResult(p, cost, dg(buf, ncost), ncost))
return p;
buf[i] = seed[i];
}
Expand All @@ -154,9 +154,9 @@ extern (C++) void* spellerX(const(char)* seed, size_t seedlen, fp_speller_t fp,
buf[i] = *s;
//printf("sub buf = '%s'\n", buf);
if (flag)
np = spellerY(buf, seedlen, fp, fparg, charset, i + 1, &ncost);
np = spellerY(buf, seedlen, dg, charset, i + 1, &ncost);
else
np = (*fp)(fparg, buf, &ncost);
np = dg(buf, ncost);
if (combineSpellerResult(p, cost, np, ncost))
return p;
}
Expand All @@ -171,9 +171,9 @@ extern (C++) void* spellerX(const(char)* seed, size_t seedlen, fp_speller_t fp,
buf[i] = *s;
//printf("ins buf = '%s'\n", buf);
if (flag)
np = spellerY(buf, seedlen + 1, fp, fparg, charset, i + 1, &ncost);
np = spellerY(buf, seedlen + 1, dg, charset, i + 1, &ncost);
else
np = (*fp)(fparg, buf, &ncost);
np = dg(buf, ncost);
if (combineSpellerResult(p, cost, np, ncost))
return p;
}
Expand All @@ -189,20 +189,19 @@ extern (C++) void* spellerX(const(char)* seed, size_t seedlen, fp_speller_t fp,
* This does an exhaustive search, so can potentially be very slow.
* Input:
* seed wrongly spelled word
* fp search function
* fparg argument to search function
* dg search delegate
* charset character set
* Returns:
* NULL no correct spellings found
* void* value returned by fp() for first possible correct spelling
* void* value returned by dg() for first possible correct spelling
*/
extern (C++) void* speller(const(char)* seed, fp_speller_t fp, void* fparg, const(char)* charset)
void* speller(const(char)* seed, scope dg_speller_t dg, const(char)* charset)
{
size_t seedlen = strlen(seed);
size_t maxdist = seedlen < 4 ? seedlen / 2 : 2;
for (int distance = 0; distance < maxdist; distance++)
{
void* p = spellerX(seed, seedlen, fp, fparg, charset, distance);
void* p = spellerX(seed, seedlen, dg, charset, distance);
if (p)
return p;
// if (seedlen > 10)
Expand All @@ -213,16 +212,7 @@ extern (C++) void* speller(const(char)* seed, fp_speller_t fp, void* fparg, cons

version (unittest)
{
extern (C++) void* speller_test(void* fparg, const(char)* s, int* cost)
{
//printf("speller_test(%s, %s)\n", fparg, s);
*cost = 0;
if (strcmp(cast(char*)fparg, s) == 0)
return fparg;
return null;
}

extern (C++) void unittest_speller()
void unittest_speller()
{
static __gshared const(char)*** cases =
[
Expand All @@ -244,12 +234,26 @@ version (unittest)
[null, null, null]
];
//printf("unittest_speller()\n");
const(void)* p = speller(cast(const(char)*)"hello", &speller_test, cast(char*)"hell", idchars);

void* dgarg;

void* speller_test(const(char)* s, ref int cost)
{
//printf("speller_test(%s, %s)\n", dgarg, s);
cost = 0;
if (strcmp(cast(char*)dgarg, s) == 0)
return dgarg;
return null;
}

dgarg = cast(char*)"hell";
const(void)* p = speller(cast(const(char)*)"hello", &speller_test, idchars);
assert(p !is null);
for (int i = 0; cases[i][0]; i++)
{
//printf("case [%d]\n", i);
void* p2 = speller(cases[i][0], &speller_test, cast(void*)cases[i][1], idchars);
dgarg = cast(void*)cases[i][1];
void* p2 = speller(cases[i][0], &speller_test, idchars);
if (p2)
assert(cases[i][2][0] == 'y');
else
Expand Down
15 changes: 0 additions & 15 deletions src/root/speller.h

This file was deleted.

24 changes: 12 additions & 12 deletions src/traits.d
Original file line number Diff line number Diff line change
Expand Up @@ -305,17 +305,6 @@ extern (C++) void initTraitsStringTable()
}
}

extern (C++) void* trait_search_fp(void* arg, const(char)* seed, int* cost)
{
//printf("trait_search_fp('%s')\n", seed);
size_t len = strlen(seed);
if (!len)
return null;
*cost = 0;
StringValue* sv = traitsStringTable.lookup(seed, len);
return sv ? cast(void*)sv.ptrvalue : null;
}

extern (C++) bool isTemplate(Dsymbol s)
{
if (!s.toAlias().isOverloadable())
Expand Down Expand Up @@ -1291,7 +1280,18 @@ extern (C++) Expression semanticTraits(TraitsExp e, Scope* sc)
}
else
{
if (const(char)* sub = cast(const(char)*)speller(e.ident.toChars(), &trait_search_fp, null, idchars))
extern (D) void* trait_search_fp(const(char)* seed, ref int cost)
{
//printf("trait_search_fp('%s')\n", seed);
size_t len = strlen(seed);
if (!len)
return null;
cost = 0;
StringValue* sv = traitsStringTable.lookup(seed, len);
return sv ? cast(void*)sv.ptrvalue : null;
}

if (auto sub = cast(const(char)*)speller(e.ident.toChars(), &trait_search_fp, idchars))
e.error("unrecognized trait '%s', did you mean '%s'?", e.ident.toChars(), sub);
else
e.error("unrecognized trait '%s'", e.ident.toChars());
Expand Down
2 changes: 1 addition & 1 deletion src/win32.mak
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ ROOTSRCD=$(ROOT)\rmem.d $(ROOT)\stringtable.d $(ROOT)\man.d $(ROOT)\port.d \
$(ROOT)\response.d $(ROOT)\rootobject.d $(ROOT)\speller.d $(ROOT)\aav.d \
$(ROOT)\longdouble.d $(ROOT)\outbuffer.d $(ROOT)\filename.d \
$(ROOT)\file.d $(ROOT)\array.d
ROOTSRC= $(ROOT)\root.h $(ROOT)\stringtable.h $(ROOT)\speller.h $(ROOT)\aav.h \
ROOTSRC= $(ROOT)\root.h $(ROOT)\stringtable.h $(ROOT)\aav.h \
$(ROOT)\longdouble.h $(ROOT)\outbuffer.h $(ROOT)\object.h \
$(ROOT)\filename.h $(ROOT)\file.h $(ROOT)\array.h $(ROOT)\rmem.h $(ROOTSRCC) \
$(ROOTSRCD)
Expand Down

0 comments on commit 7475ba9

Please sign in to comment.