[add] Added the calculate module to calculate Expression.
This commit is contained in:
parent
1d3ce20332
commit
ad7e005c7c
@ -1,19 +1,24 @@
|
|||||||
/// License: MIT
|
/// License: MIT
|
||||||
|
///
|
||||||
|
/// Types declared in this file are not considered at copying because of processing speed.
|
||||||
|
/// So you should add a const qual when use them after parsing.
|
||||||
|
///
|
||||||
module sjscript.Expression;
|
module sjscript.Expression;
|
||||||
|
|
||||||
import std.variant;
|
import std.algorithm,
|
||||||
|
std.meta,
|
||||||
|
std.variant;
|
||||||
|
|
||||||
///
|
///
|
||||||
struct Expression {
|
struct Expression {
|
||||||
public:
|
public:
|
||||||
///
|
///
|
||||||
Expression opBinary(string op : "+")(Term rhs) {
|
Expression opBinary(string op)(Term rhs) if (op == "+" || op == "-") {
|
||||||
|
static if (op == "-") {
|
||||||
|
rhs = rhs * -1f;
|
||||||
|
}
|
||||||
return Expression(terms ~ rhs);
|
return Expression(terms ~ rhs);
|
||||||
}
|
}
|
||||||
///
|
|
||||||
Expression opBinary(string op : "-")(Term rhs) {
|
|
||||||
return Expression(terms ~ rhs*(-1f));
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
///
|
||||||
Term[] terms;
|
Term[] terms;
|
||||||
@ -26,26 +31,19 @@ struct Term {
|
|||||||
alias Value = Algebraic!(float, string, FunctionCall, Expression);
|
alias Value = Algebraic!(float, string, FunctionCall, Expression);
|
||||||
|
|
||||||
///
|
///
|
||||||
Term opBinary(string op : "*", T)(T rhs) {
|
Term opBinary(string op, T)(T rhs) if ((op == "*" || op == "/")) {
|
||||||
static if (is(T == Term)) {
|
static if (is(T == Term)) {
|
||||||
return Term(
|
auto rnumerator = rhs.numerator;
|
||||||
numerator ~ rhs.numerator,
|
auto rdenominator = rhs.denominator;
|
||||||
denominator ~ rhs.denominator);
|
} else static if (staticIndexOf!(T, Value.AllowedTypes) >= 0) {
|
||||||
|
auto rnumerator = [Value(rhs)];
|
||||||
|
Value[] rdenominator;
|
||||||
} else {
|
} else {
|
||||||
return Term(
|
static assert(false);
|
||||||
numerator ~ Value(rhs), denominator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
///
|
|
||||||
Term opBinary(string op : "/", T)(T rhs) {
|
|
||||||
static if (is(T == Term)) {
|
|
||||||
return Term(
|
|
||||||
numerator ~ rhs.denominator,
|
|
||||||
denominator ~ rhs.numerator);
|
|
||||||
} else {
|
|
||||||
return Term(
|
|
||||||
numerator, denominator ~ Value(rhs));
|
|
||||||
}
|
}
|
||||||
|
static if (op == "/") swap(rnumerator, rdenominator);
|
||||||
|
|
||||||
|
return Term(numerator ~ rnumerator, denominator ~ rdenominator);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -59,7 +57,6 @@ struct FunctionCall {
|
|||||||
public:
|
public:
|
||||||
///
|
///
|
||||||
string name;
|
string name;
|
||||||
|
|
||||||
///
|
///
|
||||||
Expression[] args;
|
Expression[] args;
|
||||||
}
|
}
|
||||||
|
@ -24,10 +24,10 @@ struct ParametersBlock {
|
|||||||
struct Period {
|
struct Period {
|
||||||
public:
|
public:
|
||||||
///
|
///
|
||||||
size_t start;
|
float start;
|
||||||
|
|
||||||
///
|
///
|
||||||
size_t end;
|
float end;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
65
sjscript/src/sjscript/calculate.d
Normal file
65
sjscript/src/sjscript/calculate.d
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/// License: MIT
|
||||||
|
module sjscript.calculate;
|
||||||
|
|
||||||
|
import std.algorithm,
|
||||||
|
std.exception,
|
||||||
|
std.format,
|
||||||
|
std.math,
|
||||||
|
std.traits,
|
||||||
|
std.variant;
|
||||||
|
|
||||||
|
import sjscript.Expression;
|
||||||
|
|
||||||
|
///
|
||||||
|
enum IsVarStore(T) =
|
||||||
|
is(typeof((T vars, string name) => vars[name])) &&
|
||||||
|
is(ReturnType!((T vars, string name) => vars[name]) == float);
|
||||||
|
static assert(IsVarStore!(float[string]));
|
||||||
|
|
||||||
|
///
|
||||||
|
struct NullVarStore {
|
||||||
|
public:
|
||||||
|
static float opIndex(string name) {
|
||||||
|
// TODO: error handling
|
||||||
|
throw new Exception("undefined variable %s".format(name));
|
||||||
|
}
|
||||||
|
static assert(IsVarStore!NullVarStore);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
float CalculateExpression(VarStore)(in Expression expr, VarStore vars)
|
||||||
|
if (IsVarStore!VarStore) {
|
||||||
|
return expr.terms.map!(x => x.CalculateTerm(vars)).sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
float CalculateTerm(VarStore)(in Term term, VarStore vars)
|
||||||
|
if (IsVarStore!VarStore) {
|
||||||
|
auto num = 1f, den = 1f;
|
||||||
|
term.numerator.
|
||||||
|
map!(x => x.CalculateTermValue(vars)).
|
||||||
|
each!(x => num *= x);
|
||||||
|
term.denominator.
|
||||||
|
map!(x => x.CalculateTermValue(vars)).
|
||||||
|
each!(x => den *= x);
|
||||||
|
(!den.approxEqual(0)).enforce();
|
||||||
|
return num / den;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
float CalculateTermValue(VarStore)(in Term.Value value, VarStore vars)
|
||||||
|
if (IsVarStore!VarStore) {
|
||||||
|
return value.visit!(
|
||||||
|
(string name) => vars[name],
|
||||||
|
(float val) => val,
|
||||||
|
(in FunctionCall func) => func.CalculateFunction(vars),
|
||||||
|
(in Expression expr) => expr.CalculateExpression(vars));
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
float CalculateFunction(VarStore)(in FunctionCall fcall, VarStore vars)
|
||||||
|
if (IsVarStore!VarStore) {
|
||||||
|
const args = fcall.args.map!(x => x.CalculateExpression(vars));
|
||||||
|
// TODO: calling function
|
||||||
|
return 0;
|
||||||
|
}
|
@ -8,7 +8,8 @@ import dast.parse;
|
|||||||
|
|
||||||
import sjscript.Expression,
|
import sjscript.Expression,
|
||||||
sjscript.ParametersBlock,
|
sjscript.ParametersBlock,
|
||||||
sjscript.Token;
|
sjscript.Token,
|
||||||
|
sjscript.calculate;
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest {
|
unittest {
|
||||||
@ -62,12 +63,13 @@ private class RuleSet {
|
|||||||
|
|
||||||
static Period ParsePeriod(
|
static Period ParsePeriod(
|
||||||
@(TokenType.OpenBracket) Token,
|
@(TokenType.OpenBracket) Token,
|
||||||
@(TokenType.Number) Token begin,
|
Expression start,
|
||||||
@(TokenType.DoubleDot) Token,
|
@(TokenType.DoubleDot) Token,
|
||||||
@(TokenType.Number) Token end,
|
Expression end,
|
||||||
@(TokenType.CloseBracket) Token) {
|
@(TokenType.CloseBracket) Token) {
|
||||||
return Period(
|
return Period(
|
||||||
begin.text.to!float.to!int, end.text.to!float.to!int);
|
start.CalculateExpression(NullVarStore()),
|
||||||
|
end .CalculateExpression(NullVarStore()));
|
||||||
}
|
}
|
||||||
|
|
||||||
static Parameter[] ParseParameterListFirstItem(Parameter param) {
|
static Parameter[] ParseParameterListFirstItem(Parameter param) {
|
||||||
|
@ -16,7 +16,8 @@ $define shoot {
|
|||||||
translate_y += __dir_y;
|
translate_y += __dir_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
A [0..10] {
|
$define beat {0}
|
||||||
|
A [$beat..$beat+10] {
|
||||||
$define sinwave_add_x {0.5}
|
$define sinwave_add_x {0.5}
|
||||||
$define sinwave_add_y {0.5}
|
$define sinwave_add_y {0.5}
|
||||||
$define sinwave_amp_x {0.5}
|
$define sinwave_amp_x {0.5}
|
||||||
@ -24,11 +25,15 @@ A [0..10] {
|
|||||||
$define sinwave_hz {2}
|
$define sinwave_hz {2}
|
||||||
$sinwave
|
$sinwave
|
||||||
}
|
}
|
||||||
B [10..20] {
|
|
||||||
|
$define beat {10}
|
||||||
|
B [$beat..$beat+10/2] {
|
||||||
$define horming_speed {0.1}
|
$define horming_speed {0.1}
|
||||||
$horming
|
$horming
|
||||||
}
|
}
|
||||||
C [20..30] {
|
|
||||||
|
$define beat {20}
|
||||||
|
C [$beat..$beat+10/2] {
|
||||||
$define shoot_speed {0.1}
|
$define shoot_speed {0.1}
|
||||||
$shoot
|
$shoot
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user