2013-07-29 09:42:45 +00:00
|
|
|
#ifdef NALL_STRING_INTERNAL_HPP
|
|
|
|
|
|
|
|
namespace nall {
|
|
|
|
namespace Eval {
|
|
|
|
|
|
|
|
inline string evaluateExpression(Node* node) {
|
|
|
|
#define p(n) evaluateExpression(node->link[n])
|
|
|
|
switch(node->type) {
|
|
|
|
case Node::Type::Null: return "Null";
|
|
|
|
case Node::Type::Literal: return {"Literal:", node->literal};
|
|
|
|
case Node::Type::Function: return {"Function(0:", p(0), ", 1:", p(1), ")"};
|
|
|
|
case Node::Type::Subscript: return {"Subscript(0:", p(0), ", 1:", p(1), ")"};
|
|
|
|
case Node::Type::Member: return {"Member(0:", p(0), ", 1:", p(1), ")"};
|
|
|
|
case Node::Type::SuffixIncrement: return {"SuffixIncrement(0:", p(0), ")"};
|
|
|
|
case Node::Type::SuffixDecrement: return {"SuffixDecrement(0:", p(0), ")"};
|
|
|
|
case Node::Type::Reference: return {"Reference(0:", p(0), ")"};
|
|
|
|
case Node::Type::Dereference: return {"Dereference(0:", p(0), ")"};
|
|
|
|
case Node::Type::BitwiseNot: return {"Complement(0:", p(0), ")"};
|
|
|
|
case Node::Type::PrefixIncrement: return {"PrefixIncrement(0:", p(0), ")"};
|
|
|
|
case Node::Type::PrefixDecrement: return {"PrefixDecrement(0:", p(0), ")"};
|
|
|
|
case Node::Type::Add: return {"Add(0:", p(0), ", 1:", p(1), ")"};
|
|
|
|
case Node::Type::Multiply: return {"Multiply(0:", p(0), ", 1:", p(1), ")"};
|
|
|
|
case Node::Type::Concatenate: return {"Concatenate(0:", p(0), ", ", p(1), ")"};
|
|
|
|
case Node::Type::Coalesce: return {"Coalesce(0:", p(0), ", ", p(1), ")"};
|
|
|
|
case Node::Type::Condition: return {"Condition(0:", p(0), ", ", p(1), ", ", p(2), ")"};
|
|
|
|
case Node::Type::Assign: return {"Assign(0:", p(0), ", ", p(1), ")"};
|
|
|
|
case Node::Type::Separator: {
|
|
|
|
string result = "Separator(";
|
|
|
|
for(auto& link : node->link) {
|
|
|
|
result.append(evaluateExpression(link), ", ");
|
|
|
|
}
|
|
|
|
return result.rtrim<1>(", ").append(")");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#undef p
|
|
|
|
|
|
|
|
throw "invalid operator";
|
|
|
|
}
|
|
|
|
|
|
|
|
inline int64_t evaluateInteger(Node* node) {
|
Update to v093r01 release.
byuu says:
Changelog:
- added SA-1 MDR; fixes bug in SD Gundam G-Next where the main
battleship was unable to fire
- added out-of-the-box support for any BSD running Clang 3.3+ (FreeBSD
10+, notably)
- added new video shader, "Display Emulation", which changes the shader
based on the emulated system
- fixed the home button to go to your default library path
- phoenix: Windows port won't send onActivate unless an item is selected
(prevents crashing on pressing enter in file dialog)
- ruby: removed vec4 position from out Vertex {} (helps AMD cards)
- shaders: updated all shaders to use texture() instead of texture2D()
(helps AMD cards)
The "Display Emulation" option works like this: when selected, it tries
to load "<path>/Video Shaders/Emulation/<systemName>.shader/"; otherwise
it falls back to the blur shader. <path> is the usual (next to binary,
then in <config>/higan, then in /usr/share/higan, etc); and <systemName>
is "Famicom", "Super Famicom", "Game Boy", "Game Boy Color", "Game Boy
Advance"
To support BSD, I had to modify the $(platform) variable to
differentiate between Linux and BSD.
As such, the new $(platform) values are:
win -> windows
osx -> macosx
x -> linux or bsd
I am also checking uname -s instead of uname -a now. No reason to
potentially match the hostname to the wrong OS type.
2013-10-21 11:45:39 +00:00
|
|
|
if(node->type == Node::Type::Literal) {
|
2013-12-03 10:01:59 +00:00
|
|
|
if(node->literal.beginsWith("0b")) return nall::binary(node->literal);
|
|
|
|
if(node->literal.beginsWith("0o")) return nall::octal(node->literal);
|
|
|
|
if(node->literal.beginsWith("0x")) return nall::hex(node->literal);
|
|
|
|
if(node->literal.beginsWith("%")) return nall::binary(node->literal);
|
|
|
|
if(node->literal.beginsWith("$")) return nall::hex(node->literal);
|
Update to v093r01 release.
byuu says:
Changelog:
- added SA-1 MDR; fixes bug in SD Gundam G-Next where the main
battleship was unable to fire
- added out-of-the-box support for any BSD running Clang 3.3+ (FreeBSD
10+, notably)
- added new video shader, "Display Emulation", which changes the shader
based on the emulated system
- fixed the home button to go to your default library path
- phoenix: Windows port won't send onActivate unless an item is selected
(prevents crashing on pressing enter in file dialog)
- ruby: removed vec4 position from out Vertex {} (helps AMD cards)
- shaders: updated all shaders to use texture() instead of texture2D()
(helps AMD cards)
The "Display Emulation" option works like this: when selected, it tries
to load "<path>/Video Shaders/Emulation/<systemName>.shader/"; otherwise
it falls back to the blur shader. <path> is the usual (next to binary,
then in <config>/higan, then in /usr/share/higan, etc); and <systemName>
is "Famicom", "Super Famicom", "Game Boy", "Game Boy Color", "Game Boy
Advance"
To support BSD, I had to modify the $(platform) variable to
differentiate between Linux and BSD.
As such, the new $(platform) values are:
win -> windows
osx -> macosx
x -> linux or bsd
I am also checking uname -s instead of uname -a now. No reason to
potentially match the hostname to the wrong OS type.
2013-10-21 11:45:39 +00:00
|
|
|
return nall::integer(node->literal);
|
|
|
|
}
|
2013-07-29 09:42:45 +00:00
|
|
|
|
|
|
|
#define p(n) evaluateInteger(node->link[n])
|
|
|
|
switch(node->type) {
|
|
|
|
case Node::Type::SuffixIncrement: return p(0);
|
|
|
|
case Node::Type::SuffixDecrement: return p(0);
|
|
|
|
case Node::Type::LogicalNot: return !p(0);
|
|
|
|
case Node::Type::BitwiseNot: return ~p(0);
|
|
|
|
case Node::Type::Positive: return +p(0);
|
|
|
|
case Node::Type::Negative: return -p(0);
|
|
|
|
case Node::Type::PrefixIncrement: return p(0) + 1;
|
|
|
|
case Node::Type::PrefixDecrement: return p(0) - 1;
|
|
|
|
case Node::Type::Multiply: return p(0) * p(1);
|
|
|
|
case Node::Type::Divide: return p(0) / p(1);
|
|
|
|
case Node::Type::Modulo: return p(0) % p(1);
|
|
|
|
case Node::Type::Add: return p(0) + p(1);
|
|
|
|
case Node::Type::Subtract: return p(0) - p(1);
|
|
|
|
case Node::Type::ShiftLeft: return p(0) << p(1);
|
|
|
|
case Node::Type::ShiftRight: return p(0) >> p(1);
|
|
|
|
case Node::Type::BitwiseAnd: return p(0) & p(1);
|
|
|
|
case Node::Type::BitwiseOr: return p(0) | p(1);
|
|
|
|
case Node::Type::BitwiseXor: return p(0) ^ p(1);
|
|
|
|
case Node::Type::Equal: return p(0) == p(1);
|
|
|
|
case Node::Type::NotEqual: return p(0) != p(1);
|
|
|
|
case Node::Type::LessThanEqual: return p(0) <= p(1);
|
|
|
|
case Node::Type::GreaterThanEqual: return p(0) >= p(1);
|
|
|
|
case Node::Type::LessThan: return p(0) < p(1);
|
|
|
|
case Node::Type::GreaterThan: return p(0) > p(1);
|
|
|
|
case Node::Type::LogicalAnd: return p(0) && p(1);
|
|
|
|
case Node::Type::LogicalOr: return p(0) || p(1);
|
|
|
|
case Node::Type::Condition: return p(0) ? p(1) : p(2);
|
|
|
|
case Node::Type::Assign: return p(1);
|
|
|
|
case Node::Type::AssignMultiply: return p(0) * p(1);
|
|
|
|
case Node::Type::AssignDivide: return p(0) / p(1);
|
|
|
|
case Node::Type::AssignModulo: return p(0) % p(1);
|
|
|
|
case Node::Type::AssignAdd: return p(0) + p(1);
|
|
|
|
case Node::Type::AssignSubtract: return p(0) - p(1);
|
|
|
|
case Node::Type::AssignShiftLeft: return p(0) << p(1);
|
|
|
|
case Node::Type::AssignShiftRight: return p(0) >> p(1);
|
|
|
|
case Node::Type::AssignBitwiseAnd: return p(0) & p(1);
|
|
|
|
case Node::Type::AssignBitwiseOr: return p(0) | p(1);
|
|
|
|
case Node::Type::AssignBitwiseXor: return p(0) ^ p(1);
|
|
|
|
}
|
|
|
|
#undef p
|
|
|
|
|
|
|
|
throw "invalid operator";
|
|
|
|
}
|
|
|
|
|
|
|
|
inline optional<int64_t> integer(const string& expression) {
|
|
|
|
try {
|
|
|
|
auto tree = new Node;
|
|
|
|
const char* p = expression;
|
|
|
|
parse(tree, p, 0);
|
|
|
|
auto result = evaluateInteger(tree);
|
|
|
|
delete tree;
|
|
|
|
return {true, result};
|
|
|
|
} catch(const char*) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline long double evaluateReal(Node* node) {
|
|
|
|
if(node->type == Node::Type::Literal) return nall::real(node->literal);
|
|
|
|
|
|
|
|
#define p(n) evaluateReal(node->link[n])
|
|
|
|
switch(node->type) {
|
|
|
|
case Node::Type::LogicalNot: return !p(0);
|
|
|
|
case Node::Type::Positive: return +p(0);
|
|
|
|
case Node::Type::Negative: return -p(0);
|
|
|
|
case Node::Type::Multiply: return p(0) * p(1);
|
|
|
|
case Node::Type::Divide: return p(0) / p(1);
|
|
|
|
case Node::Type::Add: return p(0) + p(1);
|
|
|
|
case Node::Type::Subtract: return p(0) - p(1);
|
|
|
|
case Node::Type::Equal: return p(0) == p(1);
|
|
|
|
case Node::Type::NotEqual: return p(0) != p(1);
|
|
|
|
case Node::Type::LessThanEqual: return p(0) <= p(1);
|
|
|
|
case Node::Type::GreaterThanEqual: return p(0) >= p(1);
|
|
|
|
case Node::Type::LessThan: return p(0) < p(1);
|
|
|
|
case Node::Type::GreaterThan: return p(0) > p(1);
|
|
|
|
case Node::Type::LogicalAnd: return p(0) && p(1);
|
|
|
|
case Node::Type::LogicalOr: return p(0) || p(1);
|
|
|
|
case Node::Type::Condition: return p(0) ? p(1) : p(2);
|
|
|
|
case Node::Type::Assign: return p(1);
|
|
|
|
case Node::Type::AssignMultiply: return p(0) * p(1);
|
|
|
|
case Node::Type::AssignDivide: return p(0) / p(1);
|
|
|
|
case Node::Type::AssignAdd: return p(0) + p(1);
|
|
|
|
case Node::Type::AssignSubtract: return p(0) - p(1);
|
|
|
|
}
|
|
|
|
#undef p
|
|
|
|
|
|
|
|
throw "invalid operator";
|
|
|
|
}
|
|
|
|
|
|
|
|
inline optional<long double> real(const string& expression) {
|
|
|
|
try {
|
|
|
|
auto tree = new Node;
|
|
|
|
const char* p = expression;
|
|
|
|
parse(tree, p, 0);
|
|
|
|
auto result = evaluateReal(tree);
|
|
|
|
delete tree;
|
|
|
|
return {true, result};
|
|
|
|
} catch(const char*) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|