Work in progress

This commit is contained in:
Hackerpilot 2013-10-12 12:34:14 -07:00
parent e2be6948e9
commit 072932b6ff
5 changed files with 93 additions and 47 deletions

View File

@ -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;
}

View File

@ -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);

31
notes.txt Normal file
View File

@ -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.

View File

@ -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);
}

View File

@ -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;