|
|
// Copyright (c) 1999 Microsoft Corporation. All rights reserved.
//
// Declaration of a script's control structures.
//
#pragma once
#include "englookup.h"
#include "englex.h"
//////////////////////////////////////////////////////////////////////
// Statement structures
// forward decls and collections
class Routine; typedef Slots<Routine> Routines; class Variable; typedef Slots<Variable> Variables; class ReferenceName; typedef Slots<ReferenceName> ReferenceNames; class VariableReference; typedef Slots<VariableReference> VariableReferences; class Statement; typedef Slots<Statement> Statements; class Value; typedef Slots<Value> Values; class Call; typedef Slots<Call> Calls; class ExprBlock; typedef Slots<ExprBlock> ExprBlocks; class IfBlock; typedef Slots<IfBlock> IfBlocks; class Assignment; typedef Slots<Assignment> Assignments;
class Variable { public: Variable(Strings::index _istrIdentifier, DISPID _dispid = DISPID_UNKNOWN) : istrIdentifier(_istrIdentifier), dispid(_dispid) {}
Strings::index istrIdentifier; DISPID dispid; // this is set to a value other than DISPID_UNKNOWN if the variable is a member of the global dispatch instead of an item in the script itself
private: friend class SmartRef::Vector<Variable>; Variable() {} };
// Names used in a sequence for dereferencing attributes or function calls.
// For example, a and b in "a.b" or x and y in "x.y(3)".
class ReferenceName { public: ReferenceName(Strings::index _istrIdentifier) : istrIdentifier(_istrIdentifier) {}
Strings::index istrIdentifier; // -1 is used to end a sequence of names
private: friend class SmartRef::Vector<ReferenceName>; ReferenceName() {} };
class VariableReference { public: enum kind { _global, _local }; VariableReference(kind _k, ReferenceNames::index _irname, Variables::index _ivar) : k(_k), irname(_irname), ivar(_ivar) {}
kind k; ReferenceNames::index irname; Variables::index ivar; // slot of the first name within (global/local/temporary) variables
private: friend class SmartRef::Vector<VariableReference>; VariableReference() {} };
class Value { public: // dummy types to differentiate constructors
enum cons_numvalue {}; enum cons_strvalue {}; enum cons_varref {};
enum kind { _numvalue, _strvalue, _varref };
Value(cons_numvalue e, int iVal) : k(_numvalue) { inumvalue = iVal; } Value(cons_strvalue e, Strings::index iStr) : k(_strvalue) { istrvalue = iStr; } Value(cons_varref e, VariableReferences::index _ivarref) : k(_varref) { ivarref = _ivarref; }
kind k; union { int inumvalue; Strings::index istrvalue; VariableReferences::index ivarref; };
private: friend class SmartRef::Vector<Value>; Value() {} };
class Call { public: // dummy types to differentiate constructors
enum cons_global {}; enum cons_dereferenced {};
enum kind { _global, _dereferenced };
Call() {} // all fields are set after creation
kind k; union { Strings::index istrname; // _global
VariableReferences::index ivarref; // _dereferenced
}; ExprBlocks::index iexprParams; // doubly-terminated list of lists. each parameter is terminated with an _end block and the final parameter is also terminated with a second _end block.
};
class ExprBlock { public: // dummy types to differentiate constructors
enum cons_end {}; enum cons_op {}; enum cons_val {}; enum cons_call {}; enum cons_omitted {}; // used only in a routine call, stands for an omitted parameter
enum kind { _end = 0, _op, _val, _call, _omitted };
// Note: For unary - (negation), TOKEN_sub is used instead of TOKEN_op_minus.
ExprBlock(cons_end e) : k(_end) {} ExprBlock(cons_op e, Token __op) : k(_op) { op = __op; assert(CheckOperatorType(op, true, true, true, false) || op == TOKEN_sub); } ExprBlock(cons_val e, Values::index _ival) : k(_val) { ival = _ival; } ExprBlock(cons_call e, Calls::index _icall) : k(_call) { icall = _icall; } ExprBlock(cons_omitted e) : k(_omitted) {}
operator bool() { return k != _end; }
kind k;
union { Token op; Values::index ival; Calls::index icall; };
private: friend class SmartRef::Vector<ExprBlock>; friend class SmartRef::Stack<ExprBlock>; ExprBlock() {} };
class Assignment { public: Assignment(bool _fSet, VariableReferences::index _ivarrefLHS, ExprBlocks::index _iexprRHS) : fSet(_fSet), ivarrefLHS(_ivarrefLHS), iexprRHS(_iexprRHS) {}
bool fSet; VariableReferences::index ivarrefLHS; ExprBlocks::index iexprRHS;
private: friend class SmartRef::Vector<Assignment>; Assignment() {} };
class IfBlock { public: // _end: end of blocks without an 'else'
// _else: end of blocks with an 'else'
// _cond: a conditional block, from 'if' (first one) or 'elseif' (later ones)
enum kind { _end = 0, _else, _cond };
IfBlock() : k(_end) {} IfBlock(Statements::index _istmtBlock) : k(_else), istmtBlock(_istmtBlock) {} IfBlock(ExprBlocks::index _iexprCondition, Statements::index _istmtBlock) : k(_cond), iexprCondition(_iexprCondition), istmtBlock(_istmtBlock) {}
kind k; ExprBlocks::index iexprCondition; // only used by cond kind
Statements::index istmtBlock; // not used by end kind
};
class Statement { public: typedef int index;
// dummy types to differentiate constructors
enum cons_end {}; enum cons_asgn {}; enum cons_if {}; enum cons_call {};
enum kind { _end = 0, _if, _asgn, _call }; // _end is used as a terminator for a block of statements
Statement(cons_end e, int _iLine) : k(_end), iLine(_iLine) {} Statement(cons_asgn e, Assignments::index _iasgn, int _iLine) : k(_asgn), iLine(_iLine) { iasgn = _iasgn; } Statement(cons_if e, int _iLine) : k(_if), iLine(_iLine) { iif = 0; istmtIfTail = 0; } Statement(cons_call e, Calls::index _icall, int _iLine) : k(_call), iLine(_iLine) { icall = _icall; }
operator bool() { return k != _end; }
kind k; int iLine; union { Assignments::index iasgn; struct { IfBlocks::index iif; Statements::index istmtIfTail; }; Calls::index icall; };
private: friend class SmartRef::Vector<Statement>; Statement() {} };
class Routine { public: Routine(Strings::index _istrIdentifier) : istrIdentifier(_istrIdentifier), istmtBody(0), ivarNextLocal(0) {}
Strings::index istrIdentifier; Statements::index istmtBody; Variables::index ivarNextLocal; // while parsing, this is the next local slot to use. by runtime, this as the total number of local slots needed by the routine.
private: friend class SmartRef::Vector<Routine>; Routine() {} };
class Script { public: Script() {}
Routines routines; Variables globals; Strings strings; Statements statements; ReferenceNames rnames; VariableReferences varrefs; Values vals; Calls calls; ExprBlocks exprs; IfBlocks ifs; Assignments asgns; };
|