module volta.ir.expression

Code Map

module volta.ir.expression;


//! Base class for all expressions.
class Exp : Node
{
}

//! Base class for literal expressions.
class LiteralExp : Exp
{
public:
	exps: Exp[];
	type: Type;
}

//! A ternary expression is a shorthand if statement in the form of an
//! expression.
class Ternary : Exp
{
public:
	//! The condition to test.
	condition: Exp;
	//! Evaluate and return this if condition is true.
	ifTrue: Exp;
	//! Evaluate and return this if condition is false.
	ifFalse: Exp;


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

//! A BinOp is an operation the operates on two expressions with a given
//! operation.
class BinOp : Exp
{
public:
	enum Op
	{
		None,
		Assign,
		AddAssign,
		SubAssign,
		MulAssign,
		DivAssign,
		ModAssign,
		AndAssign,
		OrAssign,
		XorAssign,
		CatAssign,
		LSAssign,
		SRSAssign,
		RSAssign,
		PowAssign,
		OrOr,
		AndAnd,
		Or,
		Xor,
		And,
		Equal,
		NotEqual,
		Is,
		NotIs,
		Less,
		LessEqual,
		GreaterEqual,
		Greater,
		In,
		NotIn,
		LS,
		SRS,
		RS,
		Add,
		Sub,
		Cat,
		Mul,
		Div,
		Mod,
		Pow,
	}


public:
	//! The operation to perform.
	op: Op;
	//! The left hand side of the expression.
	left: Exp;
	//! The right hand side of the expression.
	right: Exp;
	//! Is an assignment generated for passing context to a closure.
	isInternalNestedAssign: bool;


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


public:
	static fn opToString(op: Op) string { }
}

//! A Unary operation is prepended to the back of an expression.
class Unary : Exp
{
public:
	enum Op
	{
		None,
		AddrOf,
		Increment,
		Decrement,
		Dereference,
		Minus,
		Plus,
		Not,
		Complement,
		New,
		TypeIdent,
		Cast,
		Dup,
	}


public:
	op: Op;
	value: Exp;
	hasArgumentList: bool;
	type: Type;
	argumentList: Exp[];
	argumentTags: Postfix.TagKind[];
	argumentLabels: string[];
	//! The constructor to call.
	ctor: Function;
	dupBeginning: Exp;
	dupEnd: Exp;
	fullShorthand: bool;


public:
	this() { }
	this(n: Type, e: Exp) { }
	this(old: Unary) { }
}

//! A postfix operation is appended to an expression.
class Postfix : Exp
{
public:
	enum Op
	{
		None,
		Identifier,
		Increment,
		Decrement,
		Call,
		Index,
		Slice,
		CreateDelegate,
		//! T.default -- default initialiser of T
		Default,
	}

	enum TagKind
	{
		None,
		Ref,
		Out,
	}


public:
	op: Op;
	child: Exp;
	arguments: Exp[];
	argumentTags: TagKind[];
	argumentLabels: string[];
	identifier: Identifier;
	memberFunction: ExpReference;
	templateInstance: Exp;
	isImplicitPropertyCall: bool;
	supressVtableLookup: bool;


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


public:
	static fn opToString(op: Op) string { }
}

//! A looked up postfix operation is appended to an expression.
class PropertyExp : Exp
{
public:
	child: Exp;
	//! For property get.
	getFn: Function;
	//! For property sets.
	setFns: Function[];
	identifier: Identifier;


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

//! A Constant is a literal value of a given type.
class Constant : Exp
{
public:
	union U
	{
	public:
		_byte: i8;
		_ubyte: u8;
		_short: i16;
		_ushort: u16;
		_int: i32;
		_uint: u32;
		_long: i64;
		_ulong: u64;
		_float: f32;
		_double: f64;
		_bool: bool;
		_pointer: void*;
	}


public:
	u: U;
	_string: string;
	isNull: bool;
	arrayData: immutable(void)[];
	type: Type;
	fromEnum: Enum;


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

//! Represents an array literal. Contains a list of expressions with (if
//! semantically sound) a common type.
class ArrayLiteral : LiteralExp
{
public:
	this() { }
	this(old: ArrayLiteral) { }
}

class AAPair : Node
{
public:
	key: Exp;
	value: Exp;


public:
	this() { }
	this(key: Exp, value: Exp) { }
	this(old: AAPair) { }
}

//! Represents an associative array literal -- a list of key/value pairs.
class AssocArray : Exp
{
public:
	pairs: AAPair[];
	//! The type of the associative array.
	type: Type;


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

//! Represents a single identifier. Replaced with ExpReference in a pass.
class IdentifierExp : Exp
{
public:
	globalLookup: bool;
	value: string;


public:
	this() { }
	this(s: string) { }
	this(old: IdentifierExp) { }
}

//! An Assert checks that a condition is true, and dies with an optional
//! message if not.
class Assert : Exp
{
public:
	condition: Exp;
	message: Exp;


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

//! A StringImport creates a string literal from a file on disk at compile
//! time.
class StringImport : Exp
{
public:
	filename: Exp;


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

//! The typeid expression returns the typeinfo of a given type or
//! expression.
class Typeid : Exp
{
public:
	exp: Exp;
	type: Type;
	tinfoType: Type;


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

//! The is expression is a bit of a swiss army knife. It can be simply used
//! to determine whether a given type is well-formed, or if a given type is
//! a certain other type, or can be converted into another type.
class IsExp : Exp
{
public:
	enum Specialisation
	{
		None,
		Type,
		Struct,
		Union,
		Class,
		Interface,
		Enum,
		Function,
		Delegate,
		Super,
		Const,
		Immutable,
		Inout,
		Shared,
		Return,
	}

	enum Comparison
	{
		None,
		Implicit,
		Exact,
		TraitsWord,
	}


public:
	type: Type;
	specialisation: Specialisation;
	specType: Type;
	compType: Comparison;
	traitsWord: string;
	traitsModifier: string;


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

class FunctionParameter : Node
{
public:
	type: Type;
	name: string;


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

//! A function literal can define a normal function, or a delegate (a
//! function with context). There are multiple ways to define these but the
//! long hand way is int function(int a, int b) { return a + b; } Defines a
//! function that takes two integers and returns them added up. int
//! delegate(int a, int b) { return a + b + c; } Is the same, except it has
//! access to the outer scope's variables.
class FunctionLiteral : Exp
{
public:
	isDelegate: bool;
	returnType: Type;
	params: FunctionParameter[];
	block: BlockStatement;
	singleLambdaParam: string;
	lambdaExp: Exp;


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

//! An ExpReference replaces chained postfix look ups with the result of
//! the lookup. A cache that is inserted later, in other words.
class ExpReference : Exp
{
public:
	idents: string[];
	decl: Declaration;
	//! A raw get to a function to bypass @property.
	rawReference: bool;
	doNotRewriteAsNestedLookup: bool;
	isSuperOrThisCall: bool;


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

//! A StructLiteral is an expression form of a struct.
class StructLiteral : LiteralExp
{
public:
	this() { }
	this(old: StructLiteral) { }
}

//! A UnionLiteral is a compiler internal expression form of a struct
class UnionLiteral : LiteralExp
{
public:
	this() { }
	this(old: UnionLiteral) { }
}

//! A ClassLiteral is a compiler internal expression form of a class.
class ClassLiteral : LiteralExp
{
public:
	useBaseStorage: bool;


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

//! A TypeExp is used when a primitive type is used in an expression. This
//! is currently limited to .max/min and (void*).max/min.
class TypeExp : Exp
{
public:
	type: Type;


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

//! A StoreExp is used when a NamedType is used in an expression within a
//! WithStatement, like so: with (Class.Enum) { int val = DeclInEnum; }.
class StoreExp : Exp
{
public:
	idents: string[];
	store: Store;


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

//! A StatementExp is a internal expression for inserting statements into a
//! expression. Note that this is not a function and executes the
//! statements just as if they where inserted in the BlockStatement that
//! the StatementExp is in. Meaning any ReturnStatement will return the
//! current function not this StatementExp.
class StatementExp : Exp
{
public:
	//! A list of statements to be executed.
	statements: Node[];
	//! The value of the StatementExp
	exp: Exp;
	//! If this was lowered from something, the original will go here.
	originalExp: Exp;


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

//! Expression that corresponds to what was once special tokens. FUNCTION, 
//! PRETTY_FUNCTION, FILE, and __LINE.
class TokenExp : Exp
{
public:
	enum Type
	{
		//! Just the function name. (e.g. math.add)
		Function,
		//! Full signature. (e.g. int math.add(int a, int b))
		PrettyFunction,
		//! Current file. (e.g. foo.volt)
		File,
		//! Current line number. (e.g. 32)
		Line,
		//! Current file loc. (e.g. expression.d:933
		Location,
	}


public:
	type: Type;


public:
	this(type: TokenExp.Type) { }
	this(old: TokenExp) { }
}

//! Expression that assists in working with varargs.
class VaArgExp : Exp
{
public:
	arg: Exp;
	type: Type;


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

//! Representing a expression that is working on inbuilt types.
class BuiltinExp : Exp
{
public:
	enum Kind
	{
		//! Invalid.
		Invalid,
		//! arr.ptr
		ArrayPtr,
		//! arr.length
		ArrayLength,
		//! new arr[..]
		ArrayDup,
		//! aa.length
		AALength,
		//! aa.keys
		AAKeys,
		//! aa.values
		AAValues,
		//! aa.rehash
		AARehash,
		//! aa.get
		AAGet,
		//! aa.remove
		AARemove,
		//! "foo" in aa
		AAIn,
		//! new aa[..]
		AADup,
		//! '(exp).func'()
		UFCS,
		//! obj.classinfo
		Classinfo,
		//! s := StructName(structArg)
		PODCtor,
		//! va_start(vl)
		VaStart,
		//! va_arg!i32(vl)
		VaArg,
		//! va_end(vl)
		VaEnd,
		//! Build a class vtable.
		BuildVtable,
		//! The body of a toSink(sink, enum) function.
		EnumMembers,
	}


public:
	//! What kind of builtin is this.
	kind: Kind;
	//! The type of this exp, helps keeping the typer simple.
	type: Type;
	//! Common child exp.
	children: Exp[];
	//! For UFCS, PODCtor, EnumMembers, and VaArg.
	functions: Function[];
	//! For BuildVtable.
	_class: Class;
	//! For BuildVtable.
	functionSink: FunctionSink;
	//! For EnumMembers
	_enum: Enum;


public:
	this(kind: Kind, type: Type, children: Exp[]) { }
	this(kind: Kind, type: Type, _class: Class, functionSink: FunctionSink) { }
	this(old: BuiltinExp) { }
}

//! An expression that represents a simple identifier.identifier lookup.
class AccessExp : Exp
{
public:
	//! The instance we're looking up. (instance).field
	child: Exp;
	//! The field we're looking up. instance.(field)
	field: Variable;
	//! Cached instance type.
	aggregate: Type;


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

//! An expression that forces the compiler to evaluate another expression
//! at compile time.
class RunExp : Exp
{
public:
	//! The expression to run.
	child: Exp;


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

//! A string that contains expressions to be formatted inline.
class ComposableString : Exp
{
public:
	//! True if it wasn't prefixed by 'new'.
	compileTimeOnly: bool;
	//! The components for the string, those that were contained in ${}.
	components: Exp[];


public:
	this() { }
	this(old: ComposableString) { }
}
class Exp : Node

Base class for all expressions.

class LiteralExp : Exp

Base class for literal expressions.

class Ternary : Exp

A ternary expression is a shorthand if statement in the form of an expression.

condition ? ifTrue : ifFalse

is equivalent to calling a function with a body of

if (condition) return ifTrue; else return ifFalse;

condition: Exp

The condition to test.

ifTrue: Exp

Evaluate and return this if condition is true.

ifFalse: Exp

Evaluate and return this if condition is false.

class BinOp : Exp

A BinOp is an operation the operates on two expressions with a given operation.

This includes assignment. The composite assign operators (e.g. AddAssign, +=) will be lowered out before the backend sees them.

op: Op

The operation to perform.

left: Exp

The left hand side of the expression.

right: Exp

The right hand side of the expression.

isInternalNestedAssign: bool

Is an assignment generated for passing context to a closure.

class Unary : Exp

A Unary operation is prepended to the back of an expression.

ctor: Function

The constructor to call.

class Postfix : Exp

A postfix operation is appended to an expression.

class PropertyExp : Exp

A looked up postfix operation is appended to an expression.

getFn: Function

For property get.

setFns: Function[]

For property sets.

class Constant : Exp

A Constant is a literal value of a given type.

class ArrayLiteral : LiteralExp

Represents an array literal. Contains a list of expressions with (if semantically sound) a common type.

class AssocArray : Exp

Represents an associative array literal -- a list of key/value pairs.

type: Type

The type of the associative array.

class IdentifierExp : Exp

Represents a single identifier. Replaced with ExpReference in a pass.

class Assert : Exp

An Assert checks that a condition is true, and dies with an optional message if not.

class StringImport : Exp

A StringImport creates a string literal from a file on disk at compile time.

class Typeid : Exp

The typeid expression returns the typeinfo of a given type or expression.

class IsExp : Exp

The is expression is a bit of a swiss army knife. It can be simply used to determine whether a given type is well-formed, or if a given type is a certain other type, or can be converted into another type.

Mostly useful for generic code. Not to be confused with the BinOp 'is' which checks the identity of pointers and things.

class FunctionLiteral : Exp

A function literal can define a normal function, or a delegate (a function with context). There are multiple ways to define these but the long hand way is int function(int a, int b) { return a + b; } Defines a function that takes two integers and returns them added up. int delegate(int a, int b) { return a + b + c; } Is the same, except it has access to the outer scope's variables.

class ExpReference : Exp

An ExpReference replaces chained postfix look ups with the result of the lookup. A cache that is inserted later, in other words.

rawReference: bool

A raw get to a function to bypass @property.

class StructLiteral : LiteralExp

A StructLiteral is an expression form of a struct.

class UnionLiteral : LiteralExp

A UnionLiteral is a compiler internal expression form of a struct

class ClassLiteral : LiteralExp

A ClassLiteral is a compiler internal expression form of a class.

class TypeExp : Exp

A TypeExp is used when a primitive type is used in an expression. This is currently limited to .max/min and (void*).max/min.

class StoreExp : Exp

A StoreExp is used when a NamedType is used in an expression within a WithStatement, like so: with (Class.Enum) { int val = DeclInEnum; }.

It needs to be a Scope and not a Type because it can refer to packages and modules. And we need to restart the postfix resolver process.

class StatementExp : Exp

A StatementExp is a internal expression for inserting statements into a expression. Note that this is not a function and executes the statements just as if they where inserted in the BlockStatement that the StatementExp is in. Meaning any ReturnStatement will return the current function not this StatementExp.

statements: Node[]

A list of statements to be executed.

exp: Exp

The value of the StatementExp

originalExp: Exp

If this was lowered from something, the original will go here.

class TokenExp : Exp

Expression that corresponds to what was once special tokens. FUNCTION, PRETTY_FUNCTION, FILE, and __LINE.

class VaArgExp : Exp

Expression that assists in working with varargs.

class BuiltinExp : Exp

Representing a expression that is working on inbuilt types.

A lot of code assumes that this class not be subclassed, do not remove the final it.

kind: Kind

What kind of builtin is this.

type: Type

The type of this exp, helps keeping the typer simple.

children: Exp[]

Common child exp.

functions: Function[]

For UFCS, PODCtor, EnumMembers, and VaArg.

_class: Class

For BuildVtable.

functionSink: FunctionSink

For BuildVtable.

_enum: Enum

For EnumMembers

class AccessExp : Exp

An expression that represents a simple identifier.identifier lookup.

child: Exp

The instance we're looking up. (instance).field

field: Variable

The field we're looking up. instance.(field)

aggregate: Type

Cached instance type.

class RunExp : Exp

An expression that forces the compiler to evaluate another expression at compile time.

child: Exp

The expression to run.

class ComposableString : Exp

A string that contains expressions to be formatted inline.

compileTimeOnly: bool

True if it wasn't prefixed by 'new'.

components: Exp[]

The components for the string, those that were contained in ${}.