# HG changeset patch # User Aziz K?ksal # Date 1200257581 -3600 # Node ID b2fc028d8b550ff5c75b09c41855d356faef4ad7 # Parent 14e99ce74d0616ad2bee22a8537af4f7c1d8a5a7 Added class Visitor. Moved enums NodeCategory and NodeKind to new module dil.ast.NodesEnum. Commented out some version(D2) statements. Added new module dil.semantic.Pass1. diff -r 14e99ce74d06 -r b2fc028d8b55 trunk/src/dil/ast/Expressions.d --- a/trunk/src/dil/ast/Expressions.d Sun Jan 13 19:26:12 2008 +0100 +++ b/trunk/src/dil/ast/Expressions.d Sun Jan 13 21:53:01 2008 +0100 @@ -1056,8 +1056,8 @@ } } -version(D2) -{ +// version(D2) +// { class TraitsExpression : Expression { Identifier* ident; @@ -1070,7 +1070,7 @@ this.targs = targs; } } -} +// } class VoidInitializer : Expression { diff -r 14e99ce74d06 -r b2fc028d8b55 trunk/src/dil/ast/Node.d --- a/trunk/src/dil/ast/Node.d Sun Jan 13 19:26:12 2008 +0100 +++ b/trunk/src/dil/ast/Node.d Sun Jan 13 21:53:01 2008 +0100 @@ -7,216 +7,7 @@ import common; public import dil.lexer.Token; - -enum NodeCategory -{ - Declaration, - Statement, - Expression, - Type, - Other -} - -enum NodeKind -{ - // Declarations: - Declarations, - EmptyDeclaration, - IllegalDeclaration, - ModuleDeclaration, - ImportDeclaration, - AliasDeclaration, - TypedefDeclaration, - EnumDeclaration, - ClassDeclaration, - InterfaceDeclaration, - StructDeclaration, - UnionDeclaration, - ConstructorDeclaration, - StaticConstructorDeclaration, - DestructorDeclaration, - StaticDestructorDeclaration, - FunctionDeclaration, - VariableDeclaration, - InvariantDeclaration, - UnittestDeclaration, - DebugDeclaration, - VersionDeclaration, - StaticIfDeclaration, - StaticAssertDeclaration, - TemplateDeclaration, - NewDeclaration, - DeleteDeclaration, - AttributeDeclaration, - ProtectionDeclaration, - StorageClassDeclaration, - LinkageDeclaration, - AlignDeclaration, - PragmaDeclaration, - MixinDeclaration, - - // Statements: - Statements, - IllegalStatement, - EmptyStatement, - ScopeStatement, - LabeledStatement, - ExpressionStatement, - DeclarationStatement, - IfStatement, - ConditionalStatement, - WhileStatement, - DoWhileStatement, - ForStatement, - ForeachStatement, - ForeachRangeStatement, // D2.0 - SwitchStatement, - CaseStatement, - DefaultStatement, - ContinueStatement, - BreakStatement, - ReturnStatement, - GotoStatement, - WithStatement, - SynchronizedStatement, - TryStatement, - CatchBody, - FinallyBody, - ScopeGuardStatement, - ThrowStatement, - VolatileStatement, - AsmStatement, - AsmInstruction, - AsmAlignStatement, - IllegalAsmInstruction, - PragmaStatement, - MixinStatement, - StaticIfStatement, - StaticAssertStatement, - DebugStatement, - VersionStatement, - - // Expressions: - EmptyExpression, - BinaryExpression, - CondExpression, - CommaExpression, - OrOrExpression, - AndAndExpression, - OrExpression, - XorExpression, - AndExpression, - CmpExpression, - EqualExpression, - IdentityExpression, - RelExpression, - InExpression, - LShiftExpression, - RShiftExpression, - URShiftExpression, - PlusExpression, - MinusExpression, - CatExpression, - MulExpression, - DivExpression, - ModExpression, - AssignExpression, - LShiftAssignExpression, - RShiftAssignExpression, - URShiftAssignExpression, - OrAssignExpression, - AndAssignExpression, - PlusAssignExpression, - MinusAssignExpression, - DivAssignExpression, - MulAssignExpression, - ModAssignExpression, - XorAssignExpression, - CatAssignExpression, - UnaryExpression, - AddressExpression, - PreIncrExpression, - PreDecrExpression, - PostIncrExpression, - PostDecrExpression, - DerefExpression, - SignExpression, - NotExpression, - CompExpression, - CallExpression, - NewExpression, - NewAnonClassExpression, - DeleteExpression, - CastExpression, - IndexExpression, - SliceExpression, - ModuleScopeExpression, - IdentifierExpression, - SpecialTokenExpression, - DotExpression, - TemplateInstanceExpression, - ThisExpression, - SuperExpression, - NullExpression, - DollarExpression, - BoolExpression, - IntExpression, - RealExpression, - ComplexExpression, - CharExpression, - StringExpression, - ArrayLiteralExpression, - AArrayLiteralExpression, - AssertExpression, - MixinExpression, - ImportExpression, - TypeofExpression, - TypeDotIdExpression, - TypeidExpression, - IsExpression, - FunctionLiteralExpression, - TraitsExpression, // D2.0 - VoidInitializer, - ArrayInitializer, - StructInitializer, - AsmTypeExpression, - AsmOffsetExpression, - AsmSegExpression, - AsmPostBracketExpression, - AsmBracketExpression, - AsmLocalSizeExpression, - AsmRegisterExpression, - - // Types: - UndefinedType, - IntegralType, - QualifiedType, - ModuleScopeType, - IdentifierType, - TypeofType, - TemplateInstanceType, - PointerType, - ArrayType, - FunctionType, - DelegateType, - CFuncPointerType, - ConstType, // D2.0 - InvariantType, // D2.0 - - // Other: - FunctionBody, - Parameter, - Parameters, - BaseClass, - TemplateAliasParameter, - TemplateTypeParameter, - TemplateThisParameter, // D2.0 - TemplateValueParameter, - TemplateTupleParameter, - TemplateParameters, - TemplateArguments, - EnumMember, -} +public import dil.ast.NodesEnum; /// This string is mixed into the constructor of a class that inherits from Node. const string set_kind = `this.kind = mixin("NodeKind." ~ typeof(this).stringof);`; @@ -287,6 +78,13 @@ children is null || addChildren(children); } + Class iS(Class)() + { + if (kind == mixin("NodeKind." ~ typeof(Class).stringof)) + return cast(Class)cast(void*)this; + return null; + } + static bool isDoxygenComment(Token* token) { // Doxygen: '/+!' '/*!' '//!' return token.type == TOK.Comment && token.start[2] == '!'; diff -r 14e99ce74d06 -r b2fc028d8b55 trunk/src/dil/ast/NodesEnum.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/src/dil/ast/NodesEnum.d Sun Jan 13 21:53:01 2008 +0100 @@ -0,0 +1,232 @@ +/++ + Author: Aziz Köksal + License: GPL3 ++/ +module dil.ast.NodesEnum; + +enum NodeCategory +{ + Declaration, + Statement, + Expression, + Type, + Other +} + +/// Array of class names that inherit from Node. +static const char[][] classNames = [ + // Declarations: + "Declarations", + "EmptyDeclaration", + "IllegalDeclaration", + "ModuleDeclaration", + "ImportDeclaration", + "AliasDeclaration", + "TypedefDeclaration", + "EnumDeclaration", + "ClassDeclaration", + "InterfaceDeclaration", + "StructDeclaration", + "UnionDeclaration", + "ConstructorDeclaration", + "StaticConstructorDeclaration", + "DestructorDeclaration", + "StaticDestructorDeclaration", + "FunctionDeclaration", + "VariableDeclaration", + "InvariantDeclaration", + "UnittestDeclaration", + "DebugDeclaration", + "VersionDeclaration", + "StaticIfDeclaration", + "StaticAssertDeclaration", + "TemplateDeclaration", + "NewDeclaration", + "DeleteDeclaration", + "AttributeDeclaration", + "ProtectionDeclaration", + "StorageClassDeclaration", + "LinkageDeclaration", + "AlignDeclaration", + "PragmaDeclaration", + "MixinDeclaration", + + // Statements: + "Statements", + "IllegalStatement", + "EmptyStatement", + "ScopeStatement", + "LabeledStatement", + "ExpressionStatement", + "DeclarationStatement", + "IfStatement", +// "ConditionalStatement", + "WhileStatement", + "DoWhileStatement", + "ForStatement", + "ForeachStatement", + "ForeachRangeStatement", // D2.0 + "SwitchStatement", + "CaseStatement", + "DefaultStatement", + "ContinueStatement", + "BreakStatement", + "ReturnStatement", + "GotoStatement", + "WithStatement", + "SynchronizedStatement", + "TryStatement", + "CatchBody", + "FinallyBody", + "ScopeGuardStatement", + "ThrowStatement", + "VolatileStatement", + "AsmStatement", + "AsmInstruction", + "AsmAlignStatement", + "IllegalAsmInstruction", + "PragmaStatement", + "MixinStatement", + "StaticIfStatement", + "StaticAssertStatement", + "DebugStatement", + "VersionStatement", + + // Expressions: + "EmptyExpression", + "BinaryExpression", + "CondExpression", + "CommaExpression", + "OrOrExpression", + "AndAndExpression", + "OrExpression", + "XorExpression", + "AndExpression", + "CmpExpression", + "EqualExpression", + "IdentityExpression", + "RelExpression", + "InExpression", + "LShiftExpression", + "RShiftExpression", + "URShiftExpression", + "PlusExpression", + "MinusExpression", + "CatExpression", + "MulExpression", + "DivExpression", + "ModExpression", + "AssignExpression", + "LShiftAssignExpression", + "RShiftAssignExpression", + "URShiftAssignExpression", + "OrAssignExpression", + "AndAssignExpression", + "PlusAssignExpression", + "MinusAssignExpression", + "DivAssignExpression", + "MulAssignExpression", + "ModAssignExpression", + "XorAssignExpression", + "CatAssignExpression", + "UnaryExpression", + "AddressExpression", + "PreIncrExpression", + "PreDecrExpression", + "PostIncrExpression", + "PostDecrExpression", + "DerefExpression", + "SignExpression", + "NotExpression", + "CompExpression", + "CallExpression", + "NewExpression", + "NewAnonClassExpression", + "DeleteExpression", + "CastExpression", + "IndexExpression", + "SliceExpression", + "ModuleScopeExpression", + "IdentifierExpression", + "SpecialTokenExpression", + "DotExpression", + "TemplateInstanceExpression", + "ThisExpression", + "SuperExpression", + "NullExpression", + "DollarExpression", + "BoolExpression", + "IntExpression", + "RealExpression", + "ComplexExpression", + "CharExpression", + "StringExpression", + "ArrayLiteralExpression", + "AArrayLiteralExpression", + "AssertExpression", + "MixinExpression", + "ImportExpression", + "TypeofExpression", + "TypeDotIdExpression", + "TypeidExpression", + "IsExpression", + "FunctionLiteralExpression", + "TraitsExpression", // D2.0 + "VoidInitializer", + "ArrayInitializer", + "StructInitializer", + "AsmTypeExpression", + "AsmOffsetExpression", + "AsmSegExpression", + "AsmPostBracketExpression", + "AsmBracketExpression", + "AsmLocalSizeExpression", + "AsmRegisterExpression", + + // Types: + "UndefinedType", + "IntegralType", + "QualifiedType", + "ModuleScopeType", + "IdentifierType", + "TypeofType", + "TemplateInstanceType", + "PointerType", + "ArrayType", + "FunctionType", + "DelegateType", + "CFuncPointerType", + "ConstType", // D2.0 + "InvariantType", // D2.0 + + // Other: + "FunctionBody", + "Parameter", + "Parameters", + "BaseClass", + "TemplateAliasParameter", + "TemplateTypeParameter", + "TemplateThisParameter", // D2.0 + "TemplateValueParameter", + "TemplateTupleParameter", + "TemplateParameters", + "TemplateArguments", + "EnumMember", +]; + +char[] generateNodeKindMembers() +{ + char[] text; + foreach (className; classNames) + text ~= className ~ ","; + return text; +} +// pragma(msg, generateNodeKindMembers()); + +// enum NodeKind; +mixin( + "enum NodeKind" + "{" + ~ generateNodeKindMembers ~ + "}" +); diff -r 14e99ce74d06 -r b2fc028d8b55 trunk/src/dil/ast/Parameters.d --- a/trunk/src/dil/ast/Parameters.d Sun Jan 13 19:26:12 2008 +0100 +++ b/trunk/src/dil/ast/Parameters.d Sun Jan 13 21:53:01 2008 +0100 @@ -114,8 +114,8 @@ } } -version(D2) -{ +// version(D2) +// { class TemplateThisParameter : TemplateParameter { TypeNode specType, defType; @@ -130,7 +130,7 @@ this.defType = defType; } } -} +// } class TemplateValueParameter : TemplateParameter { diff -r 14e99ce74d06 -r b2fc028d8b55 trunk/src/dil/ast/Statements.d --- a/trunk/src/dil/ast/Statements.d Sun Jan 13 19:26:12 2008 +0100 +++ b/trunk/src/dil/ast/Statements.d Sun Jan 13 21:53:01 2008 +0100 @@ -212,8 +212,8 @@ } } -version(D2) -{ +// version(D2) +// { class ForeachRangeStatement : Statement { TOK tok; @@ -233,7 +233,7 @@ this.forBody = forBody; } } -} +// } class SwitchStatement : Statement { diff -r 14e99ce74d06 -r b2fc028d8b55 trunk/src/dil/ast/Types.d --- a/trunk/src/dil/ast/Types.d Sun Jan 13 19:26:12 2008 +0100 +++ b/trunk/src/dil/ast/Types.d Sun Jan 13 21:53:01 2008 +0100 @@ -241,8 +241,8 @@ } } -version(D2) -{ +// version(D2) +// { class ConstType : TypeNode { this(TypeNode t) @@ -262,4 +262,4 @@ mixin(set_kind); } } -} // version(D2) +// } // version(D2) diff -r 14e99ce74d06 -r b2fc028d8b55 trunk/src/dil/ast/Visitor.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/src/dil/ast/Visitor.d Sun Jan 13 21:53:01 2008 +0100 @@ -0,0 +1,128 @@ +/++ + Author: Aziz Köksal + License: GPL3 ++/ +module dil.ast.Visitor; + +import dil.ast.Node; +import dil.ast.Declarations, + dil.ast.Expressions, + dil.ast.Statements, + dil.ast.Types, + dil.ast.BaseClass, + dil.ast.Parameters; + +/++ + Generate abstract visit methods. + E.g.: + Declaration visit(ClassDeclaration); + Expression visit(CommaExpression); ++/ +char[] generateAbstractVisitMethods() +{ + char[] text; + foreach (className; classNames) + { + text ~= "returnType!(\""~className~"\")" ~ " visit(" ~ className ~ ");\n"; + } + return text; +} +// pragma(msg, generateAbstractVisitMethods()); + +/// Gets the appropriate return type for the provided class. +template returnType(char[] className) +{ + static if (is(typeof(mixin(className)) : Declaration)) + alias Declaration returnType; + else + static if (is(typeof(mixin(className)) : Statement)) + alias Statement returnType; + else + static if (is(typeof(mixin(className)) : Expression)) + alias Expression returnType; + else + static if (is(typeof(mixin(className)) : TypeNode)) + alias TypeNode returnType; + else + alias Node returnType; +} + +/++ + Generate functions which do the second dispatch. + E.g.: + Expression visitCommaExpression(Visitor visitor, CommaExpression c) + { visitor.visit(c); } + + The equivalent in the traditional Visitor pattern would be: + class CommaExpression : Expression + { + void accept(Visitor visitor) + { visitor.visit(this); } + } ++/ +char[] generateDispatchFunctions() +{ + char[] text; + foreach (className; classNames) + text ~= "returnType!(\""~className~"\") visit"~className~"(Visitor visitor, "~className~" c)\n" + "{ return visitor.visit(c); }\n"; + return text; +} +// pragma(msg, generateDispatchFunctions()); + +/++ + The vtable holds a list of function pointers to the dispatch functions. ++/ +char[] generateVTable() +{ + char[] text = "["; + foreach (className; classNames) + text ~= "cast(void*)&visit"~className~",\n"; + return text[0..$-2]~"]"; // slice away last ",\n" +} +// pragma(msg, generateVTable()); + +abstract class Visitor +{ + abstract + mixin(generateAbstractVisitMethods()); + + static + mixin(generateDispatchFunctions()); + + /// The dispatch table. + static const void*[] dispatch_vtable = mixin(generateVTable()); + static assert(dispatch_vtable.length == classNames.length, "vtable length doesn't match number of classes"); + + // Returns the dispatch function for n. + T function(Visitor,T) getDispatchFunction(T)(T n) + { + return cast(T function(Visitor,T))dispatch_vtable[n.kind]; + } + + Declaration visitD(Declaration n) + { + // Do first dispatch. Second dispatch is done in the called function. + return getDispatchFunction(n)(this, n); + } + + Statement visitS(Statement n) + { + return getDispatchFunction(n)(this, n); + } + + Expression visitE(Expression n) + { + return getDispatchFunction(n)(this, n); + } + + TypeNode visitT(TypeNode n) + { + return getDispatchFunction(n)(this, n); + } + + Node visitN(Node n) + { + return getDispatchFunction(n)(this, n); + } +} diff -r 14e99ce74d06 -r b2fc028d8b55 trunk/src/dil/semantic/Pass1.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/src/dil/semantic/Pass1.d Sun Jan 13 21:53:01 2008 +0100 @@ -0,0 +1,92 @@ +/++ + Author: Aziz Köksal + License: GPL3 ++/ +module dil.semantic.Pass1; + +import dil.ast.Visitor; +import dil.ast.Node, + dil.ast.Declarations, + dil.ast.Expressions, + dil.ast.Statements, + dil.ast.Types, + dil.ast.BaseClass, + dil.ast.Parameters; + +import dil.semantic.Symbol, + dil.semantic.Symbols, + dil.semantic.Scope; + +class SemanticPass1 : Visitor +{ + Scope scop; + + /+Scope enterScope(Symbol s) + { + return null; + }+/ + +override +{ + Declaration visit(ClassDeclaration c) + { + if (c.symbol) + return null; + c.symbol = new Class(c.name, c); + // Insert into current scope. + scop.insert(c.symbol, c.name); + // Enter a new scope. + this.scop = this.scop.enter(c.symbol); + // Continue semantic analysis. + c.decls && visitD(c.decls); + // Exit scope. + this.scop = scop.exit(); + return c; + } + + Expression visit(CommaExpression e) + { + if (!e.type) + { + e.left = visitE(e.left); + e.right = visitE(e.right); + e.type = e.right.type; + } + return e; + } + + Expression visit(OrOrExpression) + { return null; } + + Expression visit(AndAndExpression) + { return null; } + + Expression visit(MixinExpression me) + { + /+ + if (type) + return this.expr; + // TODO: + auto expr = this.expr.semantic(scop); + expr = expr.evaluate(); + if (expr is null) + return this; + auto strExpr = TryCast!(StringExpression)(expr); + if (strExpr is null) + error(scop, MSG.MixinArgumentMustBeString); + else + { + auto loc = this.begin.getLocation(); + auto filePath = loc.filePath; + auto parser = new_ExpressionParser(strExpr.getString(), filePath, scop.infoMan); + expr = parser.parse(); + expr = expr.semantic(scop); + } + this.expr = expr; + this.type = expr.type; + return expr; + +/ + return null; + } +} // override +} diff -r 14e99ce74d06 -r b2fc028d8b55 trunk/src/main.d --- a/trunk/src/main.d Sun Jan 13 19:26:12 2008 +0100 +++ b/trunk/src/main.d Sun Jan 13 21:53:01 2008 +0100 @@ -10,7 +10,9 @@ dil.lexer.Token; import dil.ast.Declarations, dil.ast.Expressions, - dil.ast.Node; + dil.ast.Node, + dil.ast.Visitor; +import dil.semantic.Pass1; import dil.Messages; import dil.Settings; import dil.SettingsLoader;