Work in progress
This commit is contained in:
parent
e2be6948e9
commit
072932b6ff
|
@ -138,6 +138,9 @@ public:
|
|||
*/
|
||||
string symbolFile;
|
||||
|
||||
/**
|
||||
* Gets all parts whose name matches the given string.
|
||||
*/
|
||||
const(ACSymbol)*[] getPartsByName(string name) const
|
||||
{
|
||||
return cast(typeof(return)) parts.filter!(a => a.name == name).array;
|
||||
|
@ -206,6 +209,7 @@ struct Scope
|
|||
}
|
||||
|
||||
ACSymbol*[] symbols;
|
||||
string[][] imports;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -18,6 +18,28 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* AST conversion takes place in several steps
|
||||
* 1. AST is converted to a tree of SemanicSymbols, a tree of ACSymbols, and a
|
||||
* tree of scopes. The following fields are set on the symbols:
|
||||
* * name
|
||||
* * location
|
||||
* * alias this
|
||||
* * base class names
|
||||
* * protection level
|
||||
* * symbol kind
|
||||
* * function call tip
|
||||
* * symbol file path
|
||||
* Import statements are recorded in the scope tree.
|
||||
* 2. Scope tree is traversed and all imports are resolved by adding appropriate
|
||||
* ACSymbol instances.
|
||||
* 3. Semantic symbol tree is traversed
|
||||
* * types are resolved
|
||||
* * base classes are resolved
|
||||
* * mixin templates are resolved
|
||||
* * alias this is resolved
|
||||
*/
|
||||
|
||||
module astconverter;
|
||||
|
||||
import std.array;
|
||||
|
@ -34,22 +56,8 @@ import messages;
|
|||
import semantic;
|
||||
import stupidlog;
|
||||
|
||||
enum SemanticType
|
||||
class FirstPass : ASTVisitor
|
||||
{
|
||||
partial,
|
||||
full
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic visitor class used for caching completions of imported modules.
|
||||
*/
|
||||
class SemanticVisitor : ASTVisitor
|
||||
{
|
||||
this (SemanticType sType)
|
||||
{
|
||||
this.semanticType = sType;
|
||||
}
|
||||
|
||||
override void visit(Constructor con)
|
||||
{
|
||||
// Log.trace(__FUNCTION__, " ", typeof(con).stringof);
|
||||
|
@ -130,13 +138,13 @@ class SemanticVisitor : ASTVisitor
|
|||
foreach (declarator; dec.declarators)
|
||||
{
|
||||
SemanticSymbol* symbol = new SemanticSymbol;
|
||||
symbol.type = t;
|
||||
symbol.protection = protection;
|
||||
symbol.acSymbol.type = t;
|
||||
symbol.kind = CompletionKind.variableName;
|
||||
symbol.name = declarator.name.value.dup;
|
||||
symbol.location = declarator.name.startIndex;
|
||||
symbol.protection = protection;
|
||||
symbol.parent = currentSymbol;
|
||||
currentSymbol.children ~= symbol;
|
||||
currentSymbol.addChild(symbol);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,7 +242,7 @@ class SemanticVisitor : ASTVisitor
|
|||
// Create scope for block statements
|
||||
override void visit(BlockStatement blockStatement)
|
||||
{
|
||||
Log.trace(__FUNCTION__, " ", typeof(blockStatement).stringof);
|
||||
// Log.trace(__FUNCTION__, " ", typeof(blockStatement).stringof);
|
||||
Scope* s = new Scope;
|
||||
s.startLocation = blockStatement.startLocation;
|
||||
s.endLocation = blockStatement.endLocation;
|
||||
|
@ -243,7 +251,7 @@ class SemanticVisitor : ASTVisitor
|
|||
{
|
||||
foreach (child; currentSymbol.children)
|
||||
{
|
||||
Log.trace("Setting ", child.name, " location");
|
||||
// Log.trace("Setting ", child.name, " location");
|
||||
child.location = s.startLocation + 1;
|
||||
}
|
||||
}
|
||||
|
@ -324,7 +332,7 @@ private:
|
|||
parameter.kind = CompletionKind.variableName;
|
||||
parameter.startLocation = p.name.startIndex;
|
||||
symbol.children ~= parameter;
|
||||
Log.trace("Parameter ", parameter.name, " added to ", symbol.name);
|
||||
// Log.trace("Parameter ", parameter.name, " added to ", symbol.name);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -393,8 +401,6 @@ private:
|
|||
|
||||
/// Current scope
|
||||
Scope* currentScope;
|
||||
|
||||
SemanticType semanticType;
|
||||
}
|
||||
|
||||
|
||||
|
@ -412,6 +418,11 @@ public:
|
|||
{
|
||||
convertSemanticSymbol(symbol);
|
||||
assert (current !is null);
|
||||
resolveTypes(current);
|
||||
}
|
||||
|
||||
void resolveTypes(const(ACSymbol*) symbol)
|
||||
{
|
||||
}
|
||||
|
||||
ACSymbol* convertSemanticSymbol(const(SemanticSymbol)* symbol)
|
||||
|
@ -545,7 +556,7 @@ private:
|
|||
else if (t.type2.symbol !is null)
|
||||
{
|
||||
if (t.type2.symbol.dot)
|
||||
Log.trace("TODO: global scoped symbol handling");
|
||||
Log.error("TODO: global scoped symbol handling");
|
||||
string[] symbolParts = expandSymbol(
|
||||
t.type2.symbol.identifierOrTemplateChain);
|
||||
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
AST → Scopes
|
||||
→ SemanticSymbol → ACSymbol
|
||||
|
||||
ModuleCache has ACSymbol tree
|
||||
Completion Context has Scopes and ACSymbol instances
|
||||
|
||||
|
||||
|
||||
Caching
|
||||
=======
|
||||
|
||||
# Load file
|
||||
# Lex
|
||||
# Parse
|
||||
# BasicSemanticVisitor generates semantic object tree
|
||||
# Semantic information used to create ACSymbol tree.
|
||||
# ACSymbol tree stored in ModuleCache
|
||||
|
||||
Completion
|
||||
==========
|
||||
|
||||
# Lex source
|
||||
# Parse
|
||||
# AST Visitor generates semantic objects and scope information
|
||||
# Semantic informaton used to create ACSymbol tree. This pass is more involved
|
||||
because it also looks at variables local to functions and other symbols
|
||||
that would not be included in the module cache.
|
||||
# Semantic and scope info used to associate ACSymbol nodes and scopes. ACSymbol
|
||||
objects store their location information. Given a blank Scope tree, a method
|
||||
can be wnitten to assign ACSymbol instances to the correct scope.
|
||||
# Autocompletion will need to only look at this simplified Scope/ACSymbol tree.
|
22
semantic.d
22
semantic.d
|
@ -30,21 +30,24 @@ import stdx.d.lexer;
|
|||
struct SemanticSymbol
|
||||
{
|
||||
public:
|
||||
/// Symbol name
|
||||
string name;
|
||||
|
||||
void name(string n) @property { acSymbol.name = n; }
|
||||
|
||||
void addChild(SemanticSymbol* child)
|
||||
{
|
||||
children ~= child;
|
||||
acSymbol.parts ~= child.acSymbol;
|
||||
}
|
||||
|
||||
/// Autocompletion symbol
|
||||
ACSymbol* acSymbol;
|
||||
|
||||
/// Base classes
|
||||
string[][] baseClasses;
|
||||
|
||||
/// Completion kind
|
||||
CompletionKind kind;
|
||||
|
||||
/// Variable type or function return type
|
||||
Type type;
|
||||
|
||||
/// Function call tip. Null if this is not a function
|
||||
string callTip;
|
||||
|
||||
/// Alias this symbols
|
||||
string[] aliasThis;
|
||||
|
||||
|
@ -54,8 +57,5 @@ public:
|
|||
/// Protection level for this symobol
|
||||
TokenType protection;
|
||||
|
||||
/// Symbol location
|
||||
size_t location;
|
||||
|
||||
mixin scopeImplementation!(SemanticSymbol);
|
||||
}
|
||||
|
|
24
stupidlog.d
24
stupidlog.d
|
@ -33,39 +33,39 @@ enum LogLevel : uint
|
|||
|
||||
struct Log
|
||||
{
|
||||
static void trace(T...)(lazy string message, T args)
|
||||
static void trace(T...)(T args)
|
||||
{
|
||||
if (level < LogLevel.trace) return;
|
||||
if (output is stdout)
|
||||
output.writeln("[\033[01;36mtrace\033[0m] " ~ message, args);
|
||||
output.writeln("[\033[01;36mtrace\033[0m] ", args);
|
||||
else
|
||||
output.writeln("[trace] " ~ message, args);
|
||||
output.writeln("[trace] ", args);
|
||||
}
|
||||
|
||||
static void info(T...)(lazy string message, T args)
|
||||
static void info(T...)(T args)
|
||||
{
|
||||
if (level < LogLevel.info) return;
|
||||
if (output is stdout)
|
||||
output.writeln("[\033[01;32minfo\033[0m ] " ~ message, args);
|
||||
output.writeln("[\033[01;32minfo\033[0m ] ", args);
|
||||
else
|
||||
output.writeln("[info ] " ~ message, args);
|
||||
output.writeln("[info ] ", args);
|
||||
}
|
||||
|
||||
static void error(T...)(lazy string message, T args)
|
||||
static void error(T...)(T args)
|
||||
{
|
||||
if (level < LogLevel.error) return;
|
||||
if (output is stdout)
|
||||
output.writeln("[\033[01;31merror\033[0m] " ~ message, args);
|
||||
output.writeln("[\033[01;31merror\033[0m] ", args);
|
||||
else
|
||||
output.writeln("[error] " ~ message, args);
|
||||
output.writeln("[error] ", args);
|
||||
}
|
||||
|
||||
static void fatal(T...)(lazy string message, T args)
|
||||
static void fatal(T...)(T args)
|
||||
{
|
||||
if (output is stdout)
|
||||
output.writeln("[\033[01;35mfatal\033[0m] " ~ message, args);
|
||||
output.writeln("[\033[01;35mfatal\033[0m] ", args);
|
||||
else
|
||||
output.writeln("[fatal] " ~ message, args);
|
||||
output.writeln("[fatal] ", args);
|
||||
}
|
||||
static LogLevel level;
|
||||
static File output;
|
||||
|
|
Loading…
Reference in New Issue