2016-01-07 08:14:33 +00:00
|
|
|
#pragma once
|
2013-07-29 09:42:45 +00:00
|
|
|
|
2016-01-07 08:14:33 +00:00
|
|
|
namespace nall { namespace Eval {
|
2013-07-29 09:42:45 +00:00
|
|
|
|
2015-11-16 08:38:05 +00:00
|
|
|
inline auto evaluateExpression(Node* node) -> string {
|
2013-07-29 09:42:45 +00:00
|
|
|
#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), ", ");
|
|
|
|
}
|
2016-05-16 09:51:12 +00:00
|
|
|
return result.trimRight(", ", 1L).append(")");
|
2013-07-29 09:42:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#undef p
|
|
|
|
|
|
|
|
throw "invalid operator";
|
|
|
|
}
|
|
|
|
|
Update to v097r14 release.
byuu says:
This is a few days old, but oh well.
This WIP changes nall,hiro,ruby,icarus back to (u)int(8,16,32,64)_t.
I'm slowly pushing for (u)int(8,16,32,64) to use my custom
Integer<Size>/Natural<Size> classes instead. But it's going to be one
hell of a struggle to get that into higan.
2016-02-16 09:11:58 +00:00
|
|
|
inline auto evaluateInteger(Node* node) -> int64_t {
|
Update to v099r14 release.
byuu says:
Changelog:
- (u)int(max,ptr) abbreviations removed; use _t suffix now [didn't feel
like they were contributing enough to be worth it]
- cleaned up nall::integer,natural,real functionality
- toInteger, toNatural, toReal for parsing strings to numbers
- fromInteger, fromNatural, fromReal for creating strings from numbers
- (string,Markup::Node,SQL-based-classes)::(integer,natural,real)
left unchanged
- template<typename T> numeral(T value, long padding, char padchar)
-> string for print() formatting
- deduces integer,natural,real based on T ... cast the value if you
want to override
- there still exists binary,octal,hex,pointer for explicit print()
formatting
- lstring -> string_vector [but using lstring = string_vector; is
declared]
- would be nice to remove the using lstring eventually ... but that'd
probably require 10,000 lines of changes >_>
- format -> string_format [no using here; format was too ambiguous]
- using integer = Integer<sizeof(int)*8>; and using natural =
Natural<sizeof(uint)*8>; declared
- for consistency with boolean. These three are meant for creating
zero-initialized values implicitly (various uses)
- R65816::io() -> idle() and SPC700::io() -> idle() [more clear; frees
up struct IO {} io; naming]
- SFC CPU, PPU, SMP use struct IO {} io; over struct (Status,Registers) {}
(status,registers); now
- still some CPU::Status status values ... they didn't really fit into
IO functionality ... will have to think about this more
- SFC CPU, PPU, SMP now use step() exclusively instead of addClocks()
calling into step()
- SFC CPU joypad1_bits, joypad2_bits were unused; killed them
- SFC PPU CGRAM moved into PPU::Screen; since nothing else uses it
- SFC PPU OAM moved into PPU::Object; since nothing else uses it
- the raw uint8[544] array is gone. OAM::read() constructs values from
the OAM::Object[512] table now
- this avoids having to determine how we want to sub-divide the two
OAM memory sections
- this also eliminates the OAM::synchronize() functionality
- probably more I'm forgetting
The FPS fluctuations are driving me insane. This WIP went from 128fps to
137fps. Settled on 133.5fps for the final build. But nothing I changed
should have affected performance at all. This level of fluctuation makes
it damn near impossible to know whether I'm speeding things up or slowing
things down with changes.
2016-07-01 11:50:32 +00:00
|
|
|
if(node->type == Node::Type::Literal) return toInteger(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";
|
|
|
|
}
|
|
|
|
|
Update to v097r14 release.
byuu says:
This is a few days old, but oh well.
This WIP changes nall,hiro,ruby,icarus back to (u)int(8,16,32,64)_t.
I'm slowly pushing for (u)int(8,16,32,64) to use my custom
Integer<Size>/Natural<Size> classes instead. But it's going to be one
hell of a struggle to get that into higan.
2016-02-16 09:11:58 +00:00
|
|
|
inline auto integer(const string& expression) -> maybe<int64_t> {
|
2013-07-29 09:42:45 +00:00
|
|
|
try {
|
|
|
|
auto tree = new Node;
|
|
|
|
const char* p = expression;
|
|
|
|
parse(tree, p, 0);
|
|
|
|
auto result = evaluateInteger(tree);
|
|
|
|
delete tree;
|
2014-02-09 05:59:46 +00:00
|
|
|
return result;
|
2013-07-29 09:42:45 +00:00
|
|
|
} catch(const char*) {
|
2014-02-09 05:59:46 +00:00
|
|
|
return nothing;
|
2013-07-29 09:42:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-16 08:38:05 +00:00
|
|
|
inline auto evaluateReal(Node* node) -> long double {
|
Update to v099r14 release.
byuu says:
Changelog:
- (u)int(max,ptr) abbreviations removed; use _t suffix now [didn't feel
like they were contributing enough to be worth it]
- cleaned up nall::integer,natural,real functionality
- toInteger, toNatural, toReal for parsing strings to numbers
- fromInteger, fromNatural, fromReal for creating strings from numbers
- (string,Markup::Node,SQL-based-classes)::(integer,natural,real)
left unchanged
- template<typename T> numeral(T value, long padding, char padchar)
-> string for print() formatting
- deduces integer,natural,real based on T ... cast the value if you
want to override
- there still exists binary,octal,hex,pointer for explicit print()
formatting
- lstring -> string_vector [but using lstring = string_vector; is
declared]
- would be nice to remove the using lstring eventually ... but that'd
probably require 10,000 lines of changes >_>
- format -> string_format [no using here; format was too ambiguous]
- using integer = Integer<sizeof(int)*8>; and using natural =
Natural<sizeof(uint)*8>; declared
- for consistency with boolean. These three are meant for creating
zero-initialized values implicitly (various uses)
- R65816::io() -> idle() and SPC700::io() -> idle() [more clear; frees
up struct IO {} io; naming]
- SFC CPU, PPU, SMP use struct IO {} io; over struct (Status,Registers) {}
(status,registers); now
- still some CPU::Status status values ... they didn't really fit into
IO functionality ... will have to think about this more
- SFC CPU, PPU, SMP now use step() exclusively instead of addClocks()
calling into step()
- SFC CPU joypad1_bits, joypad2_bits were unused; killed them
- SFC PPU CGRAM moved into PPU::Screen; since nothing else uses it
- SFC PPU OAM moved into PPU::Object; since nothing else uses it
- the raw uint8[544] array is gone. OAM::read() constructs values from
the OAM::Object[512] table now
- this avoids having to determine how we want to sub-divide the two
OAM memory sections
- this also eliminates the OAM::synchronize() functionality
- probably more I'm forgetting
The FPS fluctuations are driving me insane. This WIP went from 128fps to
137fps. Settled on 133.5fps for the final build. But nothing I changed
should have affected performance at all. This level of fluctuation makes
it damn near impossible to know whether I'm speeding things up or slowing
things down with changes.
2016-07-01 11:50:32 +00:00
|
|
|
if(node->type == Node::Type::Literal) return toReal(node->literal);
|
2013-07-29 09:42:45 +00:00
|
|
|
|
|
|
|
#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";
|
|
|
|
}
|
|
|
|
|
2015-11-16 08:38:05 +00:00
|
|
|
inline auto real(const string& expression) -> maybe<long double> {
|
2013-07-29 09:42:45 +00:00
|
|
|
try {
|
|
|
|
auto tree = new Node;
|
|
|
|
const char* p = expression;
|
|
|
|
parse(tree, p, 0);
|
|
|
|
auto result = evaluateReal(tree);
|
|
|
|
delete tree;
|
2014-02-09 05:59:46 +00:00
|
|
|
return result;
|
2013-07-29 09:42:45 +00:00
|
|
|
} catch(const char*) {
|
2014-02-09 05:59:46 +00:00
|
|
|
return nothing;
|
2013-07-29 09:42:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-07 08:14:33 +00:00
|
|
|
}}
|