module volta.ir.toplevel

Code Map

module volta.ir.toplevel;


//! The toplevelest node.
class Module : Node
{
public:
	//! Name used for mangling.
	name: QualifiedName;
	//! Toplevel nodes.
	children: TopLevelBlock;
	//! Auto generated module name, unimportable.
	isAnonymous: bool;
	globalDocComments: string[];
	myScope: Scope;
	hasPhase1: bool;
	hasPhase2: bool;
	magicFlagD: bool;
	forceNoDebug: bool;
	gathered: bool;


public:
	this() { }
	this(old: Module) { }
	//! Get a unique number for this module.
	fn getId() size_t { }
}

//! A TopLevelBlock contains a series of nodes, appropriate for things like
//! modules, classes, structs, and so on.
class TopLevelBlock : Node
{
public:
	nodes: Node[];


public:
	this() { }
	this(old: TopLevelBlock) { }
}

//! An Import adds a module to the search path of identifiers inside the
//! module it's in.
class Import : Node
{
public:
	access: Access;
	isStatic: bool;
	names: QualifiedName[];
	bind: Identifier;
	aliases: Identifier[][];
	targetModules: Module[];


public:
	this() { }
	this(old: Import) { }
}

//! Attributes apply different behaviours and access levels to one or more
//! top level nodes. These are lowered onto the object by the attribremoval
//! pass.
class Attribute : Node
{
public:
	//! Used to specify the exact sort of attribute.
	enum Kind
	{
		Invalid,
		LinkageVolt,
		LinkageC,
		LinkageCPlusPlus,
		LinkageD,
		LinkageWindows,
		LinkagePascal,
		LinkageSystem,
		LoadDynamic,
		Align,
		Deprecated,
		Private,
		Protected,
		Public,
		Export,
		Static,
		Extern,
		Final,
		Synchronized,
		Override,
		Abstract,
		Const,
		Auto,
		Scope,
		Global,
		Local,
		Shared,
		Immutable,
		Inout,
		Disable,
		Property,
		Trusted,
		System,
		Safe,
		NoThrow,
		Pure,
		MangledName,
		Label,
	}


public:
	kind: Kind;
	members: TopLevelBlock;
	//! for "public abstract:"
	chain: Attribute;
	//! If kind == Annotation or MangledName.
	arguments: Exp[];
	alignAmount: i32;


public:
	this() { }
	this(old: Attribute) { }
}

//! Named is a base class for named types, like Enum, Struct, Class and so
//! on. This is slightly different from Aggregate since Enum is not a
//! Aggregate, but is a named type.
class Named : Type
{
public:
	isResolved: bool;
	access: Access;
	//! Unmangled name of the NamedType.
	name: string;
	//! Context for this NamedType.
	myScope: Scope;
	//! Filled in by the semantic pass.
	typeInfo: Variable;


public:
	this(nt: NodeType) { }
	this(nt: NodeType, old: Named) { }
}

//! Aggregate is a base class for Struct, Union & Class.
class Aggregate : Named
{
public:
	anonymousAggregates: Aggregate[];
	anonymousVars: Variable[];
	//! Toplevel nodes.
	members: TopLevelBlock;
	isActualized: bool;


public:
	this(nt: NodeType) { }
	this(nt: NodeType, old: Aggregate) { }
}

//! Plain Old Data aggregates. Struct and Union, basically.
class PODAggregate : Aggregate
{
public:
	constructors: Function[];


public:
	this(nt: NodeType) { }
	this(nt: NodeType, old: PODAggregate) { }
}

//! Java style class declaration. Classes enable polymorphism, and are
//! always accessed through opaque references (to prevent slicing -- look
//! it up!)
class Class : Aggregate
{
public:
	//! Optional.
	parent: QualifiedName;
	//! Optional.
	interfaces: QualifiedName[];
	userConstructors: Function[];
	vtableVariable: Variable;
	classinfoVariable: Variable;
	ifaceVariables: Variable[];
	initVariable: Variable;
	//! Filled in by the typeverifier.
	parentClass: Class;
	//! Filled in by the typeverifier.
	parentInterfaces: _Interface[];
	//! Filled in by the typeverifier.
	interfaceOffsets: size_t[];
	//! Filled in by the classresolver.
	methodsCache: Function[][];
	layoutStruct: Struct;
	isObject: bool;
	isAbstract: bool;
	isFinal: bool;


public:
	this() { }
	this(old: Class) { }
}

//! Java style interface declaration. An interface defines multiple
//! functions that an implementing class must define. A class can inherit
//! from multiple interfaces, and can be treated as an instance of any one
//! of them.
class _Interface : Aggregate
{
public:
	//! Super interfaces to this.
	interfaces: QualifiedName[];
	//! Filled in by the typeverifier.
	parentInterfaces: _Interface[];
	layoutStruct: Struct;


public:
	this() { }
	this(old: _Interface) { }
}

//! C style union. Structs are a POD data type, and should be binary
//! compatible with the same union as defined by your friendly
//! neighbourhood C compiler.
class Union : PODAggregate
{
public:
	totalSize: size_t;


public:
	this() { }
	this(old: Union) { }
}

//! C style struct. Structs are a POD data type, and should be binary
//! compatible with the same struct as defined by your friendly
//! neighbourhood C compiler.
class Struct : PODAggregate
{
public:
	//! If not null, this struct was lowered from this.
	loweredNode: Node;


public:
	this() { }
	this(old: Struct) { }
}

//! C style Enum. Enums create symbols that are associated with compile time
//! constants. By default, they are enumerated with ascending numbers,
//! hence the name.
class Enum : Named
{
public:
	//! At least one.
	members: EnumDeclaration[];
	base: Type;
	toSink: Function;


public:
	this() { }
	this(old: Enum) { }
}

//! Unittest code to be run on if selected by user.
class Unittest : Node
{
public:
	//! Contains statements.
	_body: BlockStatement;


public:
	this() { }
	this(old: Unittest) { }
}

//! Node represention a compile time conditional compilation.
class Condition : Node
{
public:
	//! Used to specify the exact sort of condition.
	enum Kind
	{
		Invalid,
		//! version (identifier) {}
		Version,
		//! debug {}, debug (identifier) {}
		Debug,
		//! static if (exp) {}
		StaticIf,
	}


public:
	kind: Kind;
	exp: Exp;


public:
	this() { }
	this(old: Condition) { }
}

//! Node represention a compile time conditional compilation, at the
//! toplevel. Uses Condition to specify the if it should be compiled.
class ConditionTopLevel : Node
{
public:
	condition: Condition;
	elsePresent: bool;
	members: TopLevelBlock;
	_else: TopLevelBlock;


public:
	this() { }
	this(old: ConditionTopLevel) { }
}

//! Node represention of a function mixin.
class MixinFunction : Node
{
public:
	//! Not optional.
	name: string;
	raw: BlockStatement;


public:
	this() { }
	this(old: MixinFunction) { }
}

//! Node represention of a template mixin.
class MixinTemplate : Node
{
public:
	name: string;
	raw: TopLevelBlock;


public:
	this() { }
	this(old: MixinTemplate) { }
}
class Module : Node

The toplevelest node.

In Volt, there is no truly global scope, as in C or C++ (the object module is the closest thing, and by and large the user can't change that), everything can be disambiguated by its module. This means things primitive forms of namespacing found in C (glGetString vs gl.GetString, for example) are not needed (except when interfacing with C, of course) and ambiguous names are not a major issue.

A module has name. Zero or more package names, followed by the name of the module. This name must be unique for any given run of the compiler -- two modules cannot have the same name.

The module contains the declarations that other modules can retrieve (or not retrieve, depending on access levels).

name: QualifiedName

Name used for mangling.

children: TopLevelBlock

Toplevel nodes.

isAnonymous: bool

Auto generated module name, unimportable.

fn getId() size_t

Get a unique number for this module.

class TopLevelBlock : Node

A TopLevelBlock contains a series of nodes, appropriate for things like modules, classes, structs, and so on.

This allows visitors to handle such things uniformly when needed.

class Import : Node

An Import adds a module to the search path of identifiers inside the module it's in.

For example. In a module with no imports, the symbol 'foo' is only looked for in the current module -- if it's found, there's no problem.

If we add an import, when the symbol 'foo' is looked up, nothing changes if 'foo' is found in the module with the import -- local declarations trump anything found in imports. This is to prevent changes in external modules affecting the behaviour of a program silently.

However, if there is no local 'foo', then all imported modules are modules are searched for accessible 'foo' symbols. If one is found, it is used, if more than one is found -- it is an error. This can be resolved by the user defining a local alias of that symbol (see 'local declarations trump import', above for why that works), or explicitly importing symbols, or making a module have to be accessed in long form (the.module.foo vs just foo).

class Attribute : Node

Attributes apply different behaviours and access levels to one or more top level nodes. These are lowered onto the object by the attribremoval pass.

enum Kind

Used to specify the exact sort of attribute.

chain: Attribute

for "public abstract:"

arguments: Exp[]

If kind == Annotation or MangledName.

Named is a base class for named types, like Enum, Struct, Class and so on. This is slightly different from Aggregate since Enum is not a Aggregate, but is a named type.

name: string

Unmangled name of the NamedType.

myScope: Scope

Context for this NamedType.

typeInfo: Variable

Filled in by the semantic pass.

Aggregate is a base class for Struct, Union & Class.

members: TopLevelBlock

Toplevel nodes.

class PODAggregate : Aggregate

Plain Old Data aggregates. Struct and Union, basically.

Java style class declaration. Classes enable polymorphism, and are always accessed through opaque references (to prevent slicing -- look it up!)

Classes are mangled as "C" + name.

parent: QualifiedName

Optional.

interfaces: QualifiedName[]

Optional.

parentClass: Class

Filled in by the typeverifier.

parentInterfaces: _Interface[]

Filled in by the typeverifier.

interfaceOffsets: size_t[]

Filled in by the typeverifier.

methodsCache: Function[][]

Filled in by the classresolver.

Java style interface declaration. An interface defines multiple functions that an implementing class must define. A class can inherit from multiple interfaces, and can be treated as an instance of any one of them.

interfaces: QualifiedName[]

Super interfaces to this.

parentInterfaces: _Interface[]

Filled in by the typeverifier.

C style union. Structs are a POD data type, and should be binary compatible with the same union as defined by your friendly neighbourhood C compiler.

Union are mangled as "U" + name.

C style struct. Structs are a POD data type, and should be binary compatible with the same struct as defined by your friendly neighbourhood C compiler.

Structs are mangled as "S" + name.

loweredNode: Node

If not null, this struct was lowered from this.

C style Enum. Enums create symbols that are associated with compile time constants. By default, they are enumerated with ascending numbers, hence the name.

Enums are mangled as "E" + name.

members: EnumDeclaration[]

At least one.

class Unittest : Node

Unittest code to be run on if selected by user.

_body: BlockStatement

Contains statements.

class Condition : Node

Node represention a compile time conditional compilation.

Several types Condition is collapsed into this class, including version, debug and static if. Used together with ConditionStatement and ConditionTopLevel.

enum Kind

Used to specify the exact sort of condition.

enum Version

version (identifier) {}

enum Debug

debug {}, debug (identifier) {}

enum StaticIf

static if (exp) {}

class ConditionTopLevel : Node

Node represention a compile time conditional compilation, at the toplevel. Uses Condition to specify the if it should be compiled.

class MixinFunction : Node

Node represention of a function mixin.

name: string

Not optional.

class MixinTemplate : Node

Node represention of a template mixin.