Mercurial > projects > dil
view trunk/src/dil/ast/Declarations.d @ 645:89ee7802c978
Moved semantic() methods of expressions to class SemanticPass1.
author | Aziz K?ksal <aziz.koeksal@gmail.com> |
---|---|
date | Mon, 14 Jan 2008 16:01:21 +0100 |
parents | f15b054bb27e |
children | 4ae7b13aaac8 |
line wrap: on
line source
/++ Author: Aziz Köksal License: GPL3 +/ module dil.ast.Declarations; import dil.ast.Node; import dil.ast.Expressions; import dil.ast.Types; import dil.ast.Statements; import dil.ast.Parameters; import dil.ast.BaseClass; import dil.lexer.IdTable; import dil.semantic.Scope; import dil.semantic.Analysis; import dil.semantic.Symbols; import dil.semantic.Types; import dil.Enums; import dil.Messages; import common; abstract class Declaration : Node { bool hasBody; this() { super(NodeCategory.Declaration); } // Members relevant to semantic phase. StorageClass stc; /// The storage class of this declaration. Protection prot; /// The protection attribute of this declaration. void semantic(Scope sc) { foreach (node; this.children) { assert(node !is null); if (node.category == NodeCategory.Declaration) (cast(Declaration)cast(void*)node).semantic(sc); } } final bool isStatic() { return !!(stc & StorageClass.Static); } final bool isPublic() { return !!(prot & Protection.Public); } final void setStorageClass(StorageClass stc) { this.stc = stc; } final void setProtection(Protection prot) { this.prot = prot; } } class Declarations : Declaration { this() { hasBody = true; mixin(set_kind); } void opCatAssign(Declaration d) { addChild(d); } void opCatAssign(Declarations ds) { addChildren(ds.children); } override void semantic(Scope scop) { foreach (node; this.children) { assert(node.category == NodeCategory.Declaration); (cast(Declaration)cast(void*)node).semantic(scop); } } } /// Single semicolon. class EmptyDeclaration : Declaration { this() { mixin(set_kind); } override void semantic(Scope) {} } /++ Illegal declarations encompass all tokens that don't start a DeclarationDefinition. See_Also: dil.lexer.Token.isDeclDefStartToken() +/ class IllegalDeclaration : Declaration { this() { mixin(set_kind); } override void semantic(Scope) {} } /// FQN = fully qualified name alias Identifier*[] ModuleFQN; // Identifier(.Identifier)* class ModuleDeclaration : Declaration { Identifier* moduleName; Identifier*[] packages; this(ModuleFQN moduleFQN) { mixin(set_kind); assert(moduleFQN.length != 0); this.moduleName = moduleFQN[$-1]; this.packages = moduleFQN[0..$-1]; } char[] getFQN() { auto pname = getPackageName('.'); if (pname.length) return pname ~ "." ~ getName(); else return getName(); } char[] getName() { if (moduleName) return moduleName.str; return null; } char[] getPackageName(char separator) { char[] pname; foreach (pckg; packages) if (pckg) pname ~= pckg.str ~ separator; if (pname.length) pname = pname[0..$-1]; // Remove last separator return pname; } } class ImportDeclaration : Declaration { private alias Identifier*[] Ids; ModuleFQN[] moduleFQNs; Ids moduleAliases; Ids bindNames; Ids bindAliases; this(ModuleFQN[] moduleFQNs, Ids moduleAliases, Ids bindNames, Ids bindAliases, bool isStatic) { mixin(set_kind); this.moduleFQNs = moduleFQNs; this.moduleAliases = moduleAliases; this.bindNames = bindNames; this.bindAliases = bindAliases; if (isStatic) this.stc |= StorageClass.Static; } char[][] getModuleFQNs(char separator) { char[][] FQNs; foreach (moduleFQN; moduleFQNs) { char[] FQN; foreach (ident; moduleFQN) if (ident) FQN ~= ident.str ~ separator; FQNs ~= FQN[0..$-1]; // Remove last separator } return FQNs; } } class AliasDeclaration : Declaration { Declaration decl; this(Declaration decl) { mixin(set_kind); addChild(decl); this.decl = decl; } override void semantic(Scope scop) { /+ decl.semantic(scop); // call semantic() or do SA in if statements? if (auto fd = TryCast!(FunctionDeclaration)(decl)) { // TODO: do SA here? } else if (auto vd = TryCast!(VariableDeclaration)(decl)) { // TODO: do SA here? } +/ } } class TypedefDeclaration : Declaration { Declaration decl; this(Declaration decl) { mixin(set_kind); addChild(decl); this.decl = decl; } override void semantic(Scope scop) { /+ decl.semantic(scop); // call semantic() or do SA in if statements? if (auto fd = TryCast!(FunctionDeclaration)(decl)) { // TODO: do SA here? } else if (auto vd = TryCast!(VariableDeclaration)(decl)) { // TODO: do SA here? } +/ } } class EnumDeclaration : Declaration { Identifier* name; TypeNode baseType; EnumMember[] members; this(Identifier* name, TypeNode baseType, EnumMember[] members, bool hasBody) { super.hasBody = hasBody; mixin(set_kind); addOptChild(baseType); addOptChildren(members); this.name = name; this.baseType = baseType; this.members = members; } Enum symbol; override void semantic(Scope scop) { /+ // Create the symbol. symbol = new Enum(name, this); // Type semantics. Type type = Types.Int; // Default to integer. if (baseType) type = baseType.semantic(scop); auto enumType = new EnumType(symbol, type); // Set the base type of the enum symbol. symbol.setType(enumType); if (name) { // Insert named enum into scope. scop.insert(symbol, symbol.ident); // Create new scope. scop = scop.push(symbol); } // Semantic on members. foreach (member; members) { auto value = member.value; if (value) { // value = value.semantic(scop); // value = value.evaluate(); } auto variable = new Variable(StorageClass.Const, LinkageType.None, type, member.name, member); scop.insert(variable, variable.ident); } if (name) scop.pop(); +/ } } class EnumMember : Node { Identifier* name; Expression value; this(Identifier* name, Expression value) { super(NodeCategory.Other); mixin(set_kind); addOptChild(value); this.name = name; this.value = value; } } abstract class AggregateDeclaration : Declaration { Identifier* name; TemplateParameters tparams; Declarations decls; this(Identifier* name, TemplateParameters tparams, Declarations decls) { super.hasBody = decls !is null; this.name = name; this.tparams = tparams; this.decls = decls; } } class ClassDeclaration : AggregateDeclaration { BaseClass[] bases; this(Identifier* name, TemplateParameters tparams, BaseClass[] bases, Declarations decls) { super(name, tparams, decls); mixin(set_kind); addOptChild(tparams); addOptChildren(bases); addOptChild(decls); this.bases = bases; } Class symbol; /// The class symbol for this declaration. override void semantic(Scope scop) { if (symbol) return; symbol = new Class(name, this); // Insert into current scope. scop.insert(symbol, name); // Create a new scope. scop = scop.enter(symbol); // Continue semantic analysis. decls && decls.semantic(scop); scop.exit(); } } class InterfaceDeclaration : AggregateDeclaration { BaseClass[] bases; this(Identifier* name, TemplateParameters tparams, BaseClass[] bases, Declarations decls) { super(name, tparams, decls); mixin(set_kind); addOptChild(tparams); addOptChildren(bases); addOptChild(decls); this.bases = bases; } alias dil.semantic.Symbols.Interface Interface; Interface symbol; /// The interface symbol for this declaration. override void semantic(Scope scop) { if (symbol) return; symbol = new Interface(name, this); // Insert into current scope. scop.insert(symbol, name); // Create a new scope. scop = scop.enter(symbol); // Continue semantic analysis. decls && decls.semantic(scop); scop.exit(); } } class StructDeclaration : AggregateDeclaration { uint alignSize; this(Identifier* name, TemplateParameters tparams, Declarations decls) { super(name, tparams, decls); mixin(set_kind); addOptChild(tparams); addOptChild(decls); } void setAlignSize(uint alignSize) { this.alignSize = alignSize; } Struct symbol; /// The struct symbol for this declaration. override void semantic(Scope scop) { if (symbol) return; symbol = new Struct(name, this); // Insert into current scope. scop.insert(symbol, name); // Create a new scope. scop = scop.enter(symbol); // Continue semantic analysis. decls && decls.semantic(scop); scop.exit(); } } class UnionDeclaration : AggregateDeclaration { this(Identifier* name, TemplateParameters tparams, Declarations decls) { super(name, tparams, decls); mixin(set_kind); addOptChild(tparams); addOptChild(decls); } Union symbol; /// The union symbol for this declaration. override void semantic(Scope scop) { if (symbol) return; symbol = new Union(name, this); // Insert into current scope. scop.insert(symbol, name); // Create a new scope. scop = scop.enter(symbol); // Continue semantic analysis. decls && decls.semantic(scop); scop.exit(); } } class ConstructorDeclaration : Declaration { Parameters parameters; FunctionBody funcBody; this(Parameters parameters, FunctionBody funcBody) { super.hasBody = true; mixin(set_kind); addChild(parameters); addChild(funcBody); this.parameters = parameters; this.funcBody = funcBody; } } class StaticConstructorDeclaration : Declaration { FunctionBody funcBody; this(FunctionBody funcBody) { super.hasBody = true; mixin(set_kind); addChild(funcBody); this.funcBody = funcBody; } } class DestructorDeclaration : Declaration { FunctionBody funcBody; this(FunctionBody funcBody) { super.hasBody = true; mixin(set_kind); addChild(funcBody); this.funcBody = funcBody; } } class StaticDestructorDeclaration : Declaration { FunctionBody funcBody; this(FunctionBody funcBody) { super.hasBody = true; mixin(set_kind); addChild(funcBody); this.funcBody = funcBody; } } class FunctionDeclaration : Declaration { TypeNode returnType; Identifier* funcName; TemplateParameters tparams; Parameters params; FunctionBody funcBody; LinkageType linkageType; this(TypeNode returnType, Identifier* funcName, TemplateParameters tparams, Parameters params, FunctionBody funcBody) { super.hasBody = funcBody.funcBody !is null; mixin(set_kind); addChild(returnType); addOptChild(tparams); addChild(params); addChild(funcBody); this.returnType = returnType; this.funcName = funcName; this.tparams = tparams; this.params = params; this.funcBody = funcBody; } void setLinkageType(LinkageType linkageType) { this.linkageType = linkageType; } } class VariableDeclaration : Declaration { TypeNode typeNode; Identifier*[] idents; Expression[] values; LinkageType linkageType; this(TypeNode typeNode, Identifier*[] idents, Expression[] values) { // No empty arrays allowed. Both arrays must be of same size. assert(idents.length != 0 && idents.length == values.length); // If no type (in case of AutoDeclaration), first value mustn't be null. assert(typeNode ? 1 : values[0] !is null); mixin(set_kind); addOptChild(typeNode); foreach(value; values) addOptChild(value); this.typeNode = typeNode; this.idents = idents; this.values = values; } void setLinkageType(LinkageType linkageType) { this.linkageType = linkageType; } Variable[] variables; override void semantic(Scope scop) { Type type; if (typeNode) // Get type from typeNode. type = typeNode.semantic(scop); else { // Infer type from first initializer. auto firstValue = values[0]; // firstValue = firstValue.semantic(scop); type = firstValue.type; } assert(type !is null); // Check for interface. if (scop.isInterface) return scop.error(begin, MSG.InterfaceCantHaveVariables); // Iterate over variable identifiers in this declaration. foreach (i, ident; idents) { // Perform semantic analysis on value. // if (values[i]) // values[i] = values[i].semantic(scop); // Create a new variable symbol. // TODO: pass 'prot' to constructor. auto variable = new Variable(stc, linkageType, type, ident, this); variables ~= variable; // Add to scope. scop.insert(variable); } } } class InvariantDeclaration : Declaration { FunctionBody funcBody; this(FunctionBody funcBody) { super.hasBody = true; mixin(set_kind); addChild(funcBody); this.funcBody = funcBody; } } class UnittestDeclaration : Declaration { FunctionBody funcBody; this(FunctionBody funcBody) { super.hasBody = true; mixin(set_kind); addChild(funcBody); this.funcBody = funcBody; } } abstract class ConditionalCompilationDeclaration : Declaration { Token* spec; Token* cond; Declaration decls, elseDecls; this(Token* spec, Token* cond, Declaration decls, Declaration elseDecls) { super.hasBody = decls !is null; addOptChild(decls); addOptChild(elseDecls); this.spec = spec; this.cond = cond; this.decls = decls; this.elseDecls = elseDecls; } } class DebugDeclaration : ConditionalCompilationDeclaration { this(Token* spec, Token* cond, Declaration decls, Declaration elseDecls) { super(spec, cond, decls, elseDecls); mixin(set_kind); } } class VersionDeclaration : ConditionalCompilationDeclaration { this(Token* spec, Token* cond, Declaration decls, Declaration elseDecls) { super(spec, cond, decls, elseDecls); mixin(set_kind); } } class StaticIfDeclaration : Declaration { Expression condition; Declaration ifDecls, elseDecls; this(Expression condition, Declaration ifDecls, Declaration elseDecls) { super.hasBody = true; mixin(set_kind); addChild(condition); addOptChild(ifDecls); addOptChild(elseDecls); this.condition = condition; this.ifDecls = ifDecls; this.elseDecls = elseDecls; } } class StaticAssertDeclaration : Declaration { Expression condition, message; this(Expression condition, Expression message) { super.hasBody = true; mixin(set_kind); addChild(condition); addOptChild(message); this.condition = condition; this.message = message; } } class TemplateDeclaration : Declaration { Identifier* name; TemplateParameters tparams; Declarations decls; this(Identifier* name, TemplateParameters tparams, Declarations decls) { super.hasBody = true; mixin(set_kind); addOptChild(tparams); addChild(decls); this.name = name; this.tparams = tparams; this.decls = decls; } } class NewDeclaration : Declaration { Parameters parameters; FunctionBody funcBody; this(Parameters parameters, FunctionBody funcBody) { super.hasBody = true; mixin(set_kind); addChild(parameters); addChild(funcBody); this.parameters = parameters; this.funcBody = funcBody; } } class DeleteDeclaration : Declaration { Parameters parameters; FunctionBody funcBody; this(Parameters parameters, FunctionBody funcBody) { super.hasBody = true; mixin(set_kind); addChild(parameters); addChild(funcBody); this.parameters = parameters; this.funcBody = funcBody; } } class AttributeDeclaration : Declaration { TOK attribute; Declaration decls; this(TOK attribute, Declaration decls) { super.hasBody = true; mixin(set_kind); addChild(decls); this.attribute = attribute; this.decls = decls; } } class ProtectionDeclaration : AttributeDeclaration { Protection prot; this(Protection prot, Declaration decls) { super(cast(TOK)0, decls); mixin(set_kind); this.prot = prot; } } class StorageClassDeclaration : AttributeDeclaration { StorageClass storageClass; this(StorageClass storageClass, TOK tok, Declaration decl) { super(tok, decl); mixin(set_kind); this.storageClass = storageClass; } } class LinkageDeclaration : AttributeDeclaration { LinkageType linkageType; this(LinkageType linkageType, Declaration decls) { super(TOK.Extern, decls); mixin(set_kind); this.linkageType = linkageType; } } class AlignDeclaration : AttributeDeclaration { int size; this(int size, Declaration decls) { super(TOK.Align, decls); mixin(set_kind); this.size = size; } } class PragmaDeclaration : AttributeDeclaration { Identifier* ident; Expression[] args; this(Identifier* ident, Expression[] args, Declaration decls) { addOptChildren(args); // Add args before calling super(). super(TOK.Pragma, decls); mixin(set_kind); this.ident = ident; this.args = args; } override void semantic(Scope scop) { pragmaSemantic(scop, begin, ident, args); decls.semantic(scop); } } class MixinDeclaration : Declaration { Expression templateExpr; Identifier* mixinIdent; Expression argument; // mixin ( AssignExpression ) this(Expression templateExpr, Identifier* mixinIdent) { mixin(set_kind); addChild(templateExpr); this.templateExpr = templateExpr; this.mixinIdent = mixinIdent; } this(Expression argument) { mixin(set_kind); addChild(argument); this.argument = argument; } }