[update] Improved the exception handlings in sjplayer
.
This commit is contained in:
parent
109ae328b8
commit
79bfed8d19
@ -4,12 +4,14 @@ module sjplayer.AbstractScheduledController;
|
|||||||
import std.algorithm,
|
import std.algorithm,
|
||||||
std.array,
|
std.array,
|
||||||
std.exception,
|
std.exception,
|
||||||
|
std.format,
|
||||||
std.range.primitives,
|
std.range.primitives,
|
||||||
std.typecons;
|
std.typecons;
|
||||||
|
|
||||||
import sjscript;
|
import sjscript;
|
||||||
|
|
||||||
import sjplayer.ScheduledControllerInterface,
|
import sjplayer.ScriptRuntimeException,
|
||||||
|
sjplayer.ScheduledControllerInterface,
|
||||||
sjplayer.VarStoreInterface,
|
sjplayer.VarStoreInterface,
|
||||||
sjplayer.util.Parameter,
|
sjplayer.util.Parameter,
|
||||||
sjplayer.util.Period;
|
sjplayer.util.Period;
|
||||||
@ -34,23 +36,31 @@ abstract class AbstractScheduledController : ScheduledControllerInterface {
|
|||||||
public:
|
public:
|
||||||
float opIndex(string name) const {
|
float opIndex(string name) const {
|
||||||
if (!time_.isNull && name == "time") return time_.get;
|
if (!time_.isNull && name == "time") return time_.get;
|
||||||
return this_.GetVariable(name);
|
const temp = this_.GetVariable(name);
|
||||||
|
if (!temp.isNull) return temp.get;
|
||||||
|
|
||||||
|
throw new ScriptRuntimeException(
|
||||||
|
"unknown variable `%s`".format(name), srcline_, srcchar_);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
AbstractScheduledController this_;
|
AbstractScheduledController this_;
|
||||||
Nullable!float time_;
|
Nullable!float time_;
|
||||||
|
|
||||||
|
size_t srcline_, srcchar_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrepareOperation(ref in ParametersBlock params) {
|
void PrepareOperation(ref in ParametersBlock params) {
|
||||||
user_vars_.clear();
|
user_vars_.clear();
|
||||||
|
|
||||||
auto vars = VarStore(this);
|
auto vars = VarStore(
|
||||||
|
this, Nullable!float.init, params.pos.stline, params.pos.stchar);
|
||||||
params.parameters.
|
params.parameters.
|
||||||
filter!(x => x.type == ParameterType.OnceAssign).
|
filter!(x => x.type == ParameterType.OnceAssign).
|
||||||
each !(x => SetParameter(x, vars));
|
each !(x => SetParameter(x, vars));
|
||||||
}
|
}
|
||||||
void ProcessOperation(float time, ref in ParametersBlock params) {
|
void ProcessOperation(float time, ref in ParametersBlock params) {
|
||||||
auto vars = VarStore(this, time.nullable);
|
auto vars = VarStore(
|
||||||
|
this, time.nullable, params.pos.stline, params.pos.stchar);
|
||||||
params.parameters.
|
params.parameters.
|
||||||
filter!(x => x.type != ParameterType.OnceAssign).
|
filter!(x => x.type != ParameterType.OnceAssign).
|
||||||
each !(x => SetParameter(x, vars));
|
each !(x => SetParameter(x, vars));
|
||||||
@ -58,13 +68,21 @@ abstract class AbstractScheduledController : ScheduledControllerInterface {
|
|||||||
void FinalizeOperation(ref in ParametersBlock params) {
|
void FinalizeOperation(ref in ParametersBlock params) {
|
||||||
}
|
}
|
||||||
|
|
||||||
float GetVariable(string name) const {
|
Nullable!float GetVariable(string name) const {
|
||||||
if (name in user_vars_) return user_vars_[name];
|
if (name in user_vars_) {
|
||||||
return varstore_[name];
|
return Nullable!float(user_vars_[name]);
|
||||||
|
}
|
||||||
|
auto temp = varstore_[name];
|
||||||
|
if (!temp.isNull) return temp;
|
||||||
|
// TODO: std constants
|
||||||
|
return Nullable!float.init;
|
||||||
}
|
}
|
||||||
void SetParameter(ref in Parameter param, ref in VarStore vars) {
|
void SetParameter(ref in Parameter param, ref in VarStore vars) {
|
||||||
(param.name.length >= 2 && param.name[0..2] == "__").
|
if (param.name.length < 2 || param.name[0..2] != "__") {
|
||||||
enforce("user defined variables must be prefixed '__'");
|
throw new ScriptRuntimeException(
|
||||||
|
"user defined variables must be prefixed as '__'",
|
||||||
|
param.pos.stline, param.pos.stchar);
|
||||||
|
}
|
||||||
user_vars_[param.name] = 0;
|
user_vars_[param.name] = 0;
|
||||||
param.CalculateParameter(user_vars_[param.name], vars);
|
param.CalculateParameter(user_vars_[param.name], vars);
|
||||||
}
|
}
|
||||||
@ -114,7 +132,11 @@ ParametersBlock[] SortParametersBlock(R)(R params)
|
|||||||
|
|
||||||
auto before = Period(-1, 0);
|
auto before = Period(-1, 0);
|
||||||
foreach (param; result) {
|
foreach (param; result) {
|
||||||
(!param.period.IsPeriodIntersectedToPeriod(before)).enforce();
|
if (param.period.IsPeriodIntersectedToPeriod(before)) {
|
||||||
|
throw new ScriptRuntimeException(
|
||||||
|
"the period is duplicated",
|
||||||
|
param.pos.stline, param.pos.stchar);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -64,17 +64,17 @@ class ScheduledController(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override float GetVariable(string name) const {
|
override Nullable!float GetVariable(string name) const {
|
||||||
switch (name) {
|
switch (name) {
|
||||||
static foreach (map_name, code; ParameterNameMap) {
|
static foreach (map_name, code; ParameterNameMap) {
|
||||||
case map_name:
|
case map_name:
|
||||||
return mixin("target_."~code);
|
return Nullable!float(mixin("target_."~code));
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
static if (MatrixModificationAvailable) {
|
static if (MatrixModificationAvailable) {
|
||||||
const value = matrix_factory_.GetValueByName(name);
|
const value = matrix_factory_.GetValueByName(name);
|
||||||
if (!value.isNull) return value.get;
|
if (!value.isNull) return value;
|
||||||
}
|
}
|
||||||
return super.GetVariable(name);
|
return super.GetVariable(name);
|
||||||
}
|
}
|
||||||
|
20
sjplayer/src/sjplayer/ScriptRuntimeException.d
Normal file
20
sjplayer/src/sjplayer/ScriptRuntimeException.d
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/// License: MIT
|
||||||
|
module sjplayer.ScriptRuntimeException;
|
||||||
|
|
||||||
|
import sjscript;
|
||||||
|
|
||||||
|
///
|
||||||
|
class ScriptRuntimeException : Exception {
|
||||||
|
public:
|
||||||
|
///
|
||||||
|
this(
|
||||||
|
string msg, size_t srcline, size_t srcchar,
|
||||||
|
string file = __FILE__, size_t line = __LINE__) {
|
||||||
|
super(msg, file, line);
|
||||||
|
this.srcline = srcline;
|
||||||
|
this.srcchar = srcchar;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
size_t srcline, srcchar;
|
||||||
|
}
|
@ -2,7 +2,8 @@
|
|||||||
module sjplayer.VarStore;
|
module sjplayer.VarStore;
|
||||||
|
|
||||||
import std.exception,
|
import std.exception,
|
||||||
std.format;
|
std.format,
|
||||||
|
std.typecons;
|
||||||
|
|
||||||
import sjplayer.Actor,
|
import sjplayer.Actor,
|
||||||
sjplayer.VarStoreInterface;
|
sjplayer.VarStoreInterface;
|
||||||
@ -15,12 +16,12 @@ class VarStore : VarStoreInterface {
|
|||||||
actor_ = actor;
|
actor_ = actor;
|
||||||
}
|
}
|
||||||
|
|
||||||
override float opIndex(string name) const {
|
override Nullable!float opIndex(string name) const {
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case "actor_x": return actor_.pos.x;
|
case "actor_x": return Nullable!float(actor_.pos.x);
|
||||||
case "actor_y": return actor_.pos.y;
|
case "actor_y": return Nullable!float(actor_.pos.y);
|
||||||
|
|
||||||
default: throw new Exception("unknown variable %s".format(name));
|
default: return Nullable!float.init;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
/// License: MIT
|
/// License: MIT
|
||||||
module sjplayer.VarStoreInterface;
|
module sjplayer.VarStoreInterface;
|
||||||
|
|
||||||
|
import std.typecons;
|
||||||
|
|
||||||
import sjscript;
|
import sjscript;
|
||||||
|
|
||||||
///
|
///
|
||||||
interface VarStoreInterface {
|
interface VarStoreInterface {
|
||||||
public:
|
public:
|
||||||
///
|
///
|
||||||
float opIndex(string name) const;
|
Nullable!float opIndex(string name) const;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user