[update] Improved the exception handlings in sjplayer.

This commit is contained in:
falsycat 2019-10-10 00:00:00 +00:00
parent 109ae328b8
commit 79bfed8d19
5 changed files with 64 additions and 19 deletions

View File

@ -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;
} }

View File

@ -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);
} }

View 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;
}

View File

@ -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;
} }
} }

View File

@ -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;
} }