1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
|
#pragma once
#include "Expr.h"
#include "Block.h"
namespace storm {
namespace bs {
STORM_PKG(lang.bs);
/**
* Operator information. Create by either 'lOperator' or 'rOperator' for
* left- and right associative operators.
*/
class OpInfo : public ObjectOn<Compiler> {
STORM_CLASS;
public:
// Ctor.
STORM_CTOR OpInfo(syntax::SStr *op, Int prio, Bool leftAssoc);
// Priority. High priority is done before low priority.
// Since each priority step may contain both left- and right
// associative operators, we simply treat each priority step
// as two steps depending on the associativity. Left associative
// operators have higher priority in this case.
Int priority;
// Left associative.
Bool leftAssoc;
// Operator name.
Str *name;
// Position.
SrcPos pos;
// Shall this operator be executed before 'o'?
// The equality segments defined by this function will only contain either
// right or left associative operators.
Bool STORM_FN before(OpInfo *o);
// Helpers based on 'before'.
Bool STORM_FN after(OpInfo *o);
Bool STORM_FN eq(OpInfo *o);
// Create the meaning of this operator.
virtual Expr *STORM_FN meaning(Block *block, Expr *lhs, Expr *rhs);
// To string.
virtual void STORM_FN toS(StrBuf *to) const;
protected:
// Resolve the operator 'name' according to the normal rules. Returns 'null' if nothing usable is found.
MAYBE(Expr *) STORM_FN find(Block *block, Str *name, Expr *lhs, Expr *rhs);
MAYBE(Expr *) STORM_FN find(Block *block, Str *name, Expr *lhs, Expr *rhs, Bool strict);
};
// Create OpInfo.
OpInfo *STORM_FN lOperator(syntax::SStr *op, Int priority);
OpInfo *STORM_FN rOperator(syntax::SStr *op, Int priority);
/**
* Represents a binary operator. We need a special representation for it
* since we are not handling priority in the parser. Unary operators are
* easy to get right directly in the parser, so we handle them right there.
*/
class Operator : public Expr {
STORM_CLASS;
public:
// Ctor.
STORM_CTOR Operator(Block *block, Expr *lhs, OpInfo *op, Expr *rhs);
// Block (to get scoping info). (risk of cycles).
Block *block;
// Left- and right hand side.
Expr *lhs;
Expr *rhs;
// Operator info.
OpInfo *op;
// Alter the tree to match the priority. Returns the new leaf node.
Operator *prioritize();
// Invalidate the cached function we are about to call. Call if you alter 'lhs' or 'rhs.
void invalidate();
// Get position.
virtual SrcPos STORM_FN largePos();
// Get the meaning from the operator (intended for debugging or further transforms).
virtual Expr *STORM_FN meaning();
// Result.
virtual ExprResult STORM_FN result();
// Generate code.
virtual void STORM_FN code(CodeGen *s, CodeResult *r);
// Output.
virtual void STORM_FN toS(StrBuf *to) const;
private:
// The function call we are to execute. Lazy-loaded and invalidated by 'prioritize'.
Expr *fnCall;
};
// Create an operator, swap the operators around to follow correct priority and return the topmost one.
// This means that this function may not return a new operator always.
Operator *STORM_FN mkOperator(Block *block, Expr *lhs, OpInfo *op, Expr *rhs);
/**
* Wrap an expression in parens, so that the reordering will stop att paren boundaries.
*/
class ParenExpr : public Expr {
STORM_CLASS;
public:
STORM_CTOR ParenExpr(Expr *wrap);
// Result.
virtual ExprResult STORM_FN result();
// Code.
virtual void STORM_FN code(CodeGen *s, CodeResult *r);
// Output.
virtual void STORM_FN toS(StrBuf *to) const;
private:
// Expression we're containing.
Expr *wrap;
};
/**
* Create various operators. These do not create Operator objects, since their priority
* is decided completely at parse-time.
*/
// Element access operator.
Expr *STORM_FN accessExpr(Block *block, Expr *lhs, Expr *par);
// Prefix operator.
Expr *STORM_FN prefixOperator(Block *block, syntax::SStr *o, Expr *expr);
// Postfix operator.
Expr *STORM_FN postfixOperator(Block *block, syntax::SStr *o, Expr *expr);
// Prefix or postfix operator (there is only one variant).
Expr *STORM_FN prePostOperator(Block *block, syntax::SStr *o, Expr *expr);
}
}
|