forked from OctaForge/libcubescript
clean up cubescript.cc
parent
6a9be3885f
commit
caf30eaa03
505
cubescript.cc
505
cubescript.cc
|
@ -24,12 +24,13 @@ char *cs_dup_ostr(ostd::ConstCharRange s) {
|
|||
}
|
||||
|
||||
bool cs_check_num(ostd::ConstCharRange s) {
|
||||
if (isdigit(s[0]))
|
||||
if (isdigit(s[0])) {
|
||||
return true;
|
||||
}
|
||||
switch (s[0]) {
|
||||
case '+':
|
||||
case '-':
|
||||
return isdigit(s[1]) || (s[1] == '.' && isdigit(s[2]));
|
||||
return isdigit(s[1]) || ((s[1] == '.') && isdigit(s[2]));
|
||||
case '.':
|
||||
return isdigit(s[1]) != 0;
|
||||
default:
|
||||
|
@ -40,61 +41,73 @@ bool cs_check_num(ostd::ConstCharRange s) {
|
|||
Ident::Ident(): type(ID_UNKNOWN) {}
|
||||
|
||||
/* ID_IVAR */
|
||||
Ident::Ident(ostd::ConstCharRange n, CsInt m, CsInt x, CsInt *s,
|
||||
VarCb f, int flagsv)
|
||||
: type(ID_IVAR), flags(flagsv | (m > x ? IDF_READONLY : 0)), name(n),
|
||||
minval(m), maxval(x), cb_var(ostd::move(f)) {
|
||||
Ident::Ident(
|
||||
ostd::ConstCharRange n, CsInt m, CsInt x, CsInt *s, VarCb f, int flagsv
|
||||
):
|
||||
type(ID_IVAR), flags(flagsv | (m > x ? IDF_READONLY : 0)), name(n),
|
||||
minval(m), maxval(x), cb_var(ostd::move(f))
|
||||
{
|
||||
storage.ip = s;
|
||||
}
|
||||
|
||||
/* ID_FVAR */
|
||||
Ident::Ident(ostd::ConstCharRange n, CsFloat m, CsFloat x, CsFloat *s,
|
||||
VarCb f, int flagsv)
|
||||
: type(ID_FVAR), flags(flagsv | (m > x ? IDF_READONLY : 0)), name(n),
|
||||
minvalf(m), maxvalf(x), cb_var(ostd::move(f)) {
|
||||
Ident::Ident(
|
||||
ostd::ConstCharRange n, CsFloat m, CsFloat x, CsFloat *s,
|
||||
VarCb f, int flagsv
|
||||
):
|
||||
type(ID_FVAR), flags(flagsv | (m > x ? IDF_READONLY : 0)), name(n),
|
||||
minvalf(m), maxvalf(x), cb_var(ostd::move(f))
|
||||
{
|
||||
storage.fp = s;
|
||||
}
|
||||
|
||||
/* ID_SVAR */
|
||||
Ident::Ident(ostd::ConstCharRange n, char **s, VarCb f, int flagsv)
|
||||
: type(ID_SVAR), flags(flagsv), name(n), cb_var(ostd::move(f)) {
|
||||
Ident::Ident(ostd::ConstCharRange n, char **s, VarCb f, int flagsv):
|
||||
type(ID_SVAR), flags(flagsv), name(n), cb_var(ostd::move(f))
|
||||
{
|
||||
storage.sp = s;
|
||||
}
|
||||
|
||||
/* ID_ALIAS */
|
||||
Ident::Ident(ostd::ConstCharRange n, char *a, int flagsv)
|
||||
: type(ID_ALIAS), valtype(VAL_STR), flags(flagsv), name(n), code(nullptr),
|
||||
stack(nullptr) {
|
||||
Ident::Ident(ostd::ConstCharRange n, char *a, int flagsv):
|
||||
type(ID_ALIAS), valtype(VAL_STR), flags(flagsv), name(n), code(nullptr),
|
||||
stack(nullptr)
|
||||
{
|
||||
val.s = a;
|
||||
val.len = strlen(a);
|
||||
}
|
||||
Ident::Ident(ostd::ConstCharRange n, CsInt a, int flagsv)
|
||||
: type(ID_ALIAS), valtype(VAL_INT), flags(flagsv), name(n), code(nullptr),
|
||||
stack(nullptr) {
|
||||
Ident::Ident(ostd::ConstCharRange n, CsInt a, int flagsv):
|
||||
type(ID_ALIAS), valtype(VAL_INT), flags(flagsv), name(n), code(nullptr),
|
||||
stack(nullptr)
|
||||
{
|
||||
val.i = a;
|
||||
}
|
||||
Ident::Ident(ostd::ConstCharRange n, CsFloat a, int flagsv)
|
||||
: type(ID_ALIAS), valtype(VAL_FLOAT), flags(flagsv), name(n), code(nullptr),
|
||||
stack(nullptr) {
|
||||
Ident::Ident(ostd::ConstCharRange n, CsFloat a, int flagsv):
|
||||
type(ID_ALIAS), valtype(VAL_FLOAT), flags(flagsv), name(n), code(nullptr),
|
||||
stack(nullptr)
|
||||
{
|
||||
val.f = a;
|
||||
}
|
||||
Ident::Ident(ostd::ConstCharRange n, int flagsv)
|
||||
: type(ID_ALIAS), valtype(VAL_NULL), flags(flagsv), name(n), code(nullptr),
|
||||
stack(nullptr) {
|
||||
}
|
||||
Ident::Ident(ostd::ConstCharRange n, TaggedValue const &v, int flagsv)
|
||||
: type(ID_ALIAS), valtype(v.p_type), flags(flagsv), name(n), code(nullptr),
|
||||
stack(nullptr) {
|
||||
Ident::Ident(ostd::ConstCharRange n, int flagsv):
|
||||
type(ID_ALIAS), valtype(VAL_NULL), flags(flagsv), name(n), code(nullptr),
|
||||
stack(nullptr)
|
||||
{}
|
||||
Ident::Ident(ostd::ConstCharRange n, TaggedValue const &v, int flagsv):
|
||||
type(ID_ALIAS), valtype(v.p_type), flags(flagsv), name(n), code(nullptr),
|
||||
stack(nullptr)
|
||||
{
|
||||
val = v;
|
||||
}
|
||||
|
||||
/* ID_COMMAND */
|
||||
Ident::Ident(int t, ostd::ConstCharRange n, ostd::ConstCharRange args,
|
||||
ostd::Uint32 argmask, int numargs, CmdFunc f)
|
||||
: type(t), numargs(numargs), flags(0), name(n),
|
||||
Ident::Ident(
|
||||
int t, ostd::ConstCharRange n, ostd::ConstCharRange args,
|
||||
ostd::Uint32 argmask, int numargs, CmdFunc f
|
||||
):
|
||||
type(t), numargs(numargs), flags(0), name(n),
|
||||
cargs(!args.empty() ? cs_dup_ostr(args) : nullptr),
|
||||
argmask(argmask), cb_cftv(ostd::move(f)) {
|
||||
}
|
||||
argmask(argmask), cb_cftv(ostd::move(f))
|
||||
{}
|
||||
|
||||
void cs_init_lib_base(CsState &cs);
|
||||
|
||||
|
@ -127,11 +140,12 @@ CsState::~CsState() {
|
|||
}
|
||||
|
||||
void CsState::clear_override(Ident &id) {
|
||||
if (!(id.flags & IDF_OVERRIDDEN)) return;
|
||||
if (!(id.flags & IDF_OVERRIDDEN)) {
|
||||
return;
|
||||
}
|
||||
switch (id.type) {
|
||||
case ID_ALIAS:
|
||||
if (id.get_valtype() == VAL_STR) {
|
||||
if (!id.val.s[0]) break;
|
||||
delete[] id.val.s;
|
||||
}
|
||||
id.clean_code();
|
||||
|
@ -157,16 +171,18 @@ void CsState::clear_override(Ident &id) {
|
|||
}
|
||||
|
||||
void CsState::clear_overrides() {
|
||||
for (Ident &id: idents.iter())
|
||||
for (Ident &id: idents.iter()) {
|
||||
clear_override(id);
|
||||
}
|
||||
}
|
||||
|
||||
Ident *CsState::new_ident(ostd::ConstCharRange name, int flags) {
|
||||
Ident *id = idents.at(name);
|
||||
if (!id) {
|
||||
if (cs_check_num(name)) {
|
||||
cs_debug_code(*this, "number %s is not a valid identifier name",
|
||||
name);
|
||||
cs_debug_code(
|
||||
*this, "number %s is not a valid identifier name", name
|
||||
);
|
||||
return dummy;
|
||||
}
|
||||
id = add_ident(name, flags);
|
||||
|
@ -198,7 +214,9 @@ Ident *CsState::force_ident(TaggedValue &v) {
|
|||
|
||||
bool CsState::reset_var(ostd::ConstCharRange name) {
|
||||
Ident *id = idents.at(name);
|
||||
if (!id) return false;
|
||||
if (!id) {
|
||||
return false;
|
||||
}
|
||||
if (id->flags & IDF_READONLY) {
|
||||
cs_debug_code(*this, "variable %s is read only", id->name);
|
||||
return false;
|
||||
|
@ -209,12 +227,8 @@ bool CsState::reset_var(ostd::ConstCharRange name) {
|
|||
|
||||
void CsState::touch_var(ostd::ConstCharRange name) {
|
||||
Ident *id = idents.at(name);
|
||||
if (id) switch (id->type) {
|
||||
case ID_IVAR:
|
||||
case ID_FVAR:
|
||||
case ID_SVAR:
|
||||
if (id && id->is_var()) {
|
||||
id->changed();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,10 +237,11 @@ void CsState::set_alias(ostd::ConstCharRange name, TaggedValue &v) {
|
|||
if (id) {
|
||||
switch (id->type) {
|
||||
case ID_ALIAS:
|
||||
if (id->index < MaxArguments)
|
||||
if (id->index < MaxArguments) {
|
||||
id->set_arg(*this, v);
|
||||
else
|
||||
} else {
|
||||
id->set_alias(*this, v);
|
||||
}
|
||||
return;
|
||||
case ID_IVAR:
|
||||
set_var_int_checked(id, v.get_int());
|
||||
|
@ -238,8 +253,9 @@ void CsState::set_alias(ostd::ConstCharRange name, TaggedValue &v) {
|
|||
set_var_str_checked(id, v.get_str());
|
||||
break;
|
||||
default:
|
||||
cs_debug_code(*this, "cannot redefine builtin %s with an alias",
|
||||
id->name);
|
||||
cs_debug_code(
|
||||
*this, "cannot redefine builtin %s with an alias", id->name
|
||||
);
|
||||
break;
|
||||
}
|
||||
v.cleanup();
|
||||
|
@ -257,14 +273,17 @@ void CsState::print_var_int(Ident *id, CsInt i) {
|
|||
return;
|
||||
}
|
||||
if (id->flags & IDF_HEX) {
|
||||
if (id->maxval == 0xFFFFFF)
|
||||
writefln("%s = 0x%.6X (%d, %d, %d)", id->name,
|
||||
i, (i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF);
|
||||
else
|
||||
if (id->maxval == 0xFFFFFF) {
|
||||
writefln(
|
||||
"%s = 0x%.6X (%d, %d, %d)", id->name,
|
||||
i, (i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF
|
||||
);
|
||||
} else {
|
||||
writefln("%s = 0x%X", id->name, i);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
writefln("%s = %d", id->name, i);
|
||||
}
|
||||
}
|
||||
|
||||
void CsState::print_var_float(Ident *id, CsFloat f) {
|
||||
|
@ -272,10 +291,11 @@ void CsState::print_var_float(Ident *id, CsFloat f) {
|
|||
}
|
||||
|
||||
void CsState::print_var_str(Ident *id, ostd::ConstCharRange s) {
|
||||
if (ostd::find(s, '"').empty())
|
||||
if (ostd::find(s, '"').empty()) {
|
||||
writefln("%s = \"%s\"", id->name, s);
|
||||
else
|
||||
} else {
|
||||
writefln("%s = [%s]", id->name, s);
|
||||
}
|
||||
}
|
||||
|
||||
void CsState::print_var(Ident *id) {
|
||||
|
@ -309,7 +329,9 @@ void TaggedValue::cleanup() {
|
|||
}
|
||||
|
||||
void TaggedValue::force_null() {
|
||||
if (get_type() == VAL_NULL) return;
|
||||
if (get_type() == VAL_NULL) {
|
||||
return;
|
||||
}
|
||||
cleanup();
|
||||
set_null();
|
||||
}
|
||||
|
@ -418,14 +440,16 @@ CsFloat Ident::get_float() const {
|
|||
}
|
||||
|
||||
Bytecode *TaggedValue::get_code() const {
|
||||
if (get_type() != VAL_CODE)
|
||||
if (get_type() != VAL_CODE) {
|
||||
return nullptr;
|
||||
}
|
||||
return const_cast<Bytecode *>(code);
|
||||
}
|
||||
|
||||
Ident *TaggedValue::get_ident() const {
|
||||
if (get_type() != VAL_IDENT)
|
||||
if (get_type() != VAL_IDENT) {
|
||||
return nullptr;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
|
@ -503,9 +527,9 @@ OSTD_EXPORT bool code_is_empty(Bytecode const *code) {
|
|||
if (!code) {
|
||||
return true;
|
||||
}
|
||||
return (*reinterpret_cast<
|
||||
ostd::Uint32 const *
|
||||
>(code) & CODE_OP_MASK) == CODE_EXIT;
|
||||
return (
|
||||
*reinterpret_cast<ostd::Uint32 const *>(code) & CODE_OP_MASK
|
||||
) == CODE_EXIT;
|
||||
}
|
||||
|
||||
bool TaggedValue::code_is_empty() const {
|
||||
|
@ -604,14 +628,19 @@ void Ident::push_arg(TaggedValue const &v, IdentStack &st, bool um) {
|
|||
stack = &st;
|
||||
set_value(v);
|
||||
clean_code();
|
||||
if (um)
|
||||
if (um) {
|
||||
flags &= ~IDF_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
void Ident::pop_arg() {
|
||||
if (!stack) return;
|
||||
if (!stack) {
|
||||
return;
|
||||
}
|
||||
IdentStack *st = stack;
|
||||
if (get_valtype() == VAL_STR) delete[] val.s;
|
||||
if (get_valtype() == VAL_STR) {
|
||||
delete[] val.s;
|
||||
}
|
||||
set_value(*stack);
|
||||
clean_code();
|
||||
stack = st->next;
|
||||
|
@ -637,17 +666,22 @@ void Ident::redo_arg(IdentStack const &st) {
|
|||
}
|
||||
|
||||
void Ident::push_alias(IdentStack &stack) {
|
||||
if (type == ID_ALIAS && index >= MaxArguments)
|
||||
if (type == ID_ALIAS && index >= MaxArguments) {
|
||||
push_arg(null_value, stack);
|
||||
}
|
||||
}
|
||||
|
||||
void Ident::pop_alias() {
|
||||
if (type == ID_ALIAS && index >= MaxArguments) pop_arg();
|
||||
if (type == ID_ALIAS && index >= MaxArguments) {
|
||||
pop_arg();
|
||||
}
|
||||
}
|
||||
|
||||
void Ident::set_arg(CsState &cs, TaggedValue &v) {
|
||||
if (cs.stack->usedargs & (1 << index)) {
|
||||
if (get_valtype() == VAL_STR) delete[] val.s;
|
||||
if (get_valtype() == VAL_STR) {
|
||||
delete[] val.s;
|
||||
}
|
||||
set_value(v);
|
||||
clean_code();
|
||||
} else {
|
||||
|
@ -657,7 +691,9 @@ void Ident::set_arg(CsState &cs, TaggedValue &v) {
|
|||
}
|
||||
|
||||
void Ident::set_alias(CsState &cs, TaggedValue &v) {
|
||||
if (get_valtype() == VAL_STR) delete[] val.s;
|
||||
if (get_valtype() == VAL_STR) {
|
||||
delete[] val.s;
|
||||
}
|
||||
set_value(v);
|
||||
clean_code();
|
||||
flags = (flags & cs.identflags) | cs.identflags;
|
||||
|
@ -681,7 +717,9 @@ bool cs_override_var(CsState &cs, Ident *id, SF sf, RF rf, CF cf) {
|
|||
if (!(id->flags & IDF_OVERRIDDEN)) {
|
||||
sf();
|
||||
id->flags |= IDF_OVERRIDDEN;
|
||||
} else cf();
|
||||
} else {
|
||||
cf();
|
||||
}
|
||||
} else {
|
||||
if (id->flags & IDF_OVERRIDDEN) {
|
||||
rf();
|
||||
|
@ -692,130 +730,165 @@ bool cs_override_var(CsState &cs, Ident *id, SF sf, RF rf, CF cf) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void CsState::set_var_int(ostd::ConstCharRange name, CsInt v,
|
||||
bool dofunc, bool doclamp) {
|
||||
void CsState::set_var_int(
|
||||
ostd::ConstCharRange name, CsInt v, bool dofunc, bool doclamp
|
||||
) {
|
||||
Ident *id = idents.at(name);
|
||||
if (!id || id->type != ID_IVAR)
|
||||
if (!id || id->is_ivar()) {
|
||||
return;
|
||||
bool success = cs_override_var(*this, id,
|
||||
}
|
||||
bool success = cs_override_var(
|
||||
*this, id,
|
||||
[&id]() { id->overrideval.i = *id->storage.ip; },
|
||||
[]() {}, []() {});
|
||||
if (!success)
|
||||
[]() {}, []() {}
|
||||
);
|
||||
if (!success) {
|
||||
return;
|
||||
if (doclamp)
|
||||
}
|
||||
if (doclamp) {
|
||||
*id->storage.ip = ostd::clamp(v, id->minval, id->maxval);
|
||||
else
|
||||
} else {
|
||||
*id->storage.ip = v;
|
||||
if (dofunc)
|
||||
}
|
||||
if (dofunc) {
|
||||
id->changed();
|
||||
}
|
||||
}
|
||||
|
||||
void CsState::set_var_float(ostd::ConstCharRange name, CsFloat v,
|
||||
bool dofunc, bool doclamp) {
|
||||
void CsState::set_var_float(
|
||||
ostd::ConstCharRange name, CsFloat v, bool dofunc, bool doclamp
|
||||
) {
|
||||
Ident *id = idents.at(name);
|
||||
if (!id || id->type != ID_FVAR)
|
||||
if (!id || id->is_fvar()) {
|
||||
return;
|
||||
bool success = cs_override_var(*this, id,
|
||||
}
|
||||
bool success = cs_override_var(
|
||||
*this, id,
|
||||
[&id]() { id->overrideval.f = *id->storage.fp; },
|
||||
[]() {}, []() {});
|
||||
if (!success)
|
||||
[]() {}, []() {}
|
||||
);
|
||||
if (!success) {
|
||||
return;
|
||||
if (doclamp)
|
||||
}
|
||||
if (doclamp) {
|
||||
*id->storage.fp = ostd::clamp(v, id->minvalf, id->maxvalf);
|
||||
else
|
||||
} else {
|
||||
*id->storage.fp = v;
|
||||
if (dofunc)
|
||||
}
|
||||
if (dofunc) {
|
||||
id->changed();
|
||||
}
|
||||
}
|
||||
|
||||
void CsState::set_var_str(ostd::ConstCharRange name, ostd::ConstCharRange v,
|
||||
bool dofunc) {
|
||||
void CsState::set_var_str(
|
||||
ostd::ConstCharRange name, ostd::ConstCharRange v, bool dofunc
|
||||
) {
|
||||
Ident *id = idents.at(name);
|
||||
if (!id || id->type != ID_SVAR)
|
||||
if (!id || id->is_svar()) {
|
||||
return;
|
||||
bool success = cs_override_var(*this, id,
|
||||
}
|
||||
bool success = cs_override_var(
|
||||
*this, id,
|
||||
[&id]() { id->overrideval.s = *id->storage.sp; },
|
||||
[&id]() { delete[] id->overrideval.s; },
|
||||
[&id]() { delete[] *id->storage.sp; });
|
||||
if (!success)
|
||||
[&id]() { delete[] *id->storage.sp; }
|
||||
);
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
*id->storage.sp = cs_dup_ostr(v);
|
||||
if (dofunc)
|
||||
if (dofunc) {
|
||||
id->changed();
|
||||
}
|
||||
}
|
||||
|
||||
ostd::Maybe<CsInt> CsState::get_var_int(ostd::ConstCharRange name) {
|
||||
Ident *id = idents.at(name);
|
||||
if (!id || id->type != ID_IVAR)
|
||||
if (!id || id->is_ivar()) {
|
||||
return ostd::nothing;
|
||||
}
|
||||
return *id->storage.ip;
|
||||
}
|
||||
|
||||
ostd::Maybe<CsFloat> CsState::get_var_float(ostd::ConstCharRange name) {
|
||||
Ident *id = idents.at(name);
|
||||
if (!id || id->type != ID_FVAR)
|
||||
if (!id || id->is_fvar()) {
|
||||
return ostd::nothing;
|
||||
}
|
||||
return *id->storage.fp;
|
||||
}
|
||||
|
||||
ostd::Maybe<ostd::String> CsState::get_var_str(ostd::ConstCharRange name) {
|
||||
Ident *id = idents.at(name);
|
||||
if (!id || id->type != ID_SVAR)
|
||||
if (!id || id->is_svar()) {
|
||||
return ostd::nothing;
|
||||
}
|
||||
return ostd::String(*id->storage.sp);
|
||||
}
|
||||
|
||||
ostd::Maybe<CsInt> CsState::get_var_min_int(ostd::ConstCharRange name) {
|
||||
Ident *id = idents.at(name);
|
||||
if (!id || id->type != ID_IVAR)
|
||||
if (!id || id->is_ivar()) {
|
||||
return ostd::nothing;
|
||||
}
|
||||
return id->minval;
|
||||
}
|
||||
|
||||
ostd::Maybe<CsInt> CsState::get_var_max_int(ostd::ConstCharRange name) {
|
||||
Ident *id = idents.at(name);
|
||||
if (!id || id->type != ID_IVAR)
|
||||
if (!id || id->is_ivar()) {
|
||||
return ostd::nothing;
|
||||
}
|
||||
return id->maxval;
|
||||
}
|
||||
|
||||
ostd::Maybe<CsFloat> CsState::get_var_min_float(ostd::ConstCharRange name) {
|
||||
Ident *id = idents.at(name);
|
||||
if (!id || id->type != ID_FVAR)
|
||||
if (!id || id->is_fvar()) {
|
||||
return ostd::nothing;
|
||||
}
|
||||
return id->minvalf;
|
||||
}
|
||||
|
||||
ostd::Maybe<CsFloat> CsState::get_var_max_float(ostd::ConstCharRange name) {
|
||||
Ident *id = idents.at(name);
|
||||
if (!id || id->type != ID_FVAR)
|
||||
if (!id || id->is_fvar()) {
|
||||
return ostd::nothing;
|
||||
}
|
||||
return id->maxvalf;
|
||||
}
|
||||
|
||||
ostd::Maybe<ostd::String>
|
||||
CsState::get_alias(ostd::ConstCharRange name) {
|
||||
Ident *id = idents.at(name);
|
||||
if (!id || id->type != ID_ALIAS)
|
||||
if (!id || id->is_alias()) {
|
||||
return ostd::nothing;
|
||||
if ((id->index < MaxArguments) && !(stack->usedargs & (1 << id->index)))
|
||||
}
|
||||
if ((id->index < MaxArguments) && !(stack->usedargs & (1 << id->index))) {
|
||||
return ostd::nothing;
|
||||
}
|
||||
return ostd::move(id->get_str());
|
||||
}
|
||||
|
||||
CsInt cs_clamp_var(CsState &cs, Ident *id, CsInt v) {
|
||||
if (v < id->minval)
|
||||
if (v < id->minval) {
|
||||
v = id->minval;
|
||||
else if (v > id->maxval)
|
||||
} else if (v > id->maxval) {
|
||||
v = id->maxval;
|
||||
else
|
||||
} else {
|
||||
return v;
|
||||
cs_debug_code(cs, (id->flags & IDF_HEX)
|
||||
? ((id->minval <= 255)
|
||||
}
|
||||
cs_debug_code(
|
||||
cs,
|
||||
(id->flags & IDF_HEX)
|
||||
? (
|
||||
(id->minval <= 255)
|
||||
? "valid range for '%s' is %d..0x%X"
|
||||
: "valid range for '%s' is 0x%X..0x%X")
|
||||
: "valid range for '%s' is 0x%X..0x%X"
|
||||
)
|
||||
: "valid range for '%s' is %d..%d",
|
||||
id->name, id->minval, id->maxval);
|
||||
id->name, id->minval, id->maxval
|
||||
);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
@ -824,13 +897,17 @@ void CsState::set_var_int_checked(Ident *id, CsInt v) {
|
|||
cs_debug_code(*this, "variable '%s' is read only", id->name);
|
||||
return;
|
||||
}
|
||||
bool success = cs_override_var(*this, id,
|
||||
bool success = cs_override_var(
|
||||
*this, id,
|
||||
[&id]() { id->overrideval.i = *id->storage.ip; },
|
||||
[]() {}, []() {});
|
||||
if (!success)
|
||||
[]() {}, []() {}
|
||||
);
|
||||
if (!success) {
|
||||
return;
|
||||
if (v < id->minval || v > id->maxval)
|
||||
}
|
||||
if ((v < id->minval) || (v > id->maxval)) {
|
||||
v = cs_clamp_var(*this, id, v);
|
||||
}
|
||||
*id->storage.ip = v;
|
||||
id->changed();
|
||||
}
|
||||
|
@ -839,21 +916,25 @@ void CsState::set_var_int_checked(Ident *id, TvalRange args) {
|
|||
CsInt v = args[0].force_int();
|
||||
if ((id->flags & IDF_HEX) && (args.size() > 1)) {
|
||||
v = (v << 16) | (args[1].force_int() << 8);
|
||||
if (args.size() > 2)
|
||||
if (args.size() > 2) {
|
||||
v |= args[2].force_int();
|
||||
}
|
||||
}
|
||||
set_var_int_checked(id, v);
|
||||
}
|
||||
|
||||
CsFloat cs_clamp_fvar(CsState &cs, Ident *id, CsFloat v) {
|
||||
if (v < id->minvalf)
|
||||
if (v < id->minvalf) {
|
||||
v = id->minvalf;
|
||||
else if (v > id->maxvalf)
|
||||
} else if (v > id->maxvalf) {
|
||||
v = id->maxvalf;
|
||||
else
|
||||
} else {
|
||||
return v;
|
||||
cs_debug_code(cs, "valid range for '%s' is %s..%s", floatstr(id->minvalf),
|
||||
floatstr(id->maxvalf));
|
||||
}
|
||||
cs_debug_code(
|
||||
cs, "valid range for '%s' is %s..%s", floatstr(id->minvalf),
|
||||
floatstr(id->maxvalf)
|
||||
);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
@ -862,13 +943,17 @@ void CsState::set_var_float_checked(Ident *id, CsFloat v) {
|
|||
cs_debug_code(*this, "variable '%s' is read only", id->name);
|
||||
return;
|
||||
}
|
||||
bool success = cs_override_var(*this, id,
|
||||
bool success = cs_override_var(
|
||||
*this, id,
|
||||
[&id]() { id->overrideval.f = *id->storage.fp; },
|
||||
[]() {}, []() {});
|
||||
if (!success)
|
||||
[]() {}, []() {}
|
||||
);
|
||||
if (!success) {
|
||||
return;
|
||||
if (v < id->minvalf || v > id->maxvalf)
|
||||
}
|
||||
if ((v < id->minvalf) || (v > id->maxvalf)) {
|
||||
v = cs_clamp_fvar(*this, id, v);
|
||||
}
|
||||
*id->storage.fp = v;
|
||||
id->changed();
|
||||
}
|
||||
|
@ -878,11 +963,15 @@ void CsState::set_var_str_checked(Ident *id, ostd::ConstCharRange v) {
|
|||
cs_debug_code(*this, "variable '%s' is read only", id->name);
|
||||
return;
|
||||
}
|
||||
bool success = cs_override_var(*this, id,
|
||||
bool success = cs_override_var(
|
||||
*this, id,
|
||||
[&id]() { id->overrideval.s = *id->storage.sp; },
|
||||
[&id]() { delete[] id->overrideval.s; },
|
||||
[&id]() { delete[] *id->storage.sp; });
|
||||
if (!success) return;
|
||||
[&id]() { delete[] *id->storage.sp; }
|
||||
);
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
*id->storage.sp = cs_dup_ostr(v);
|
||||
id->changed();
|
||||
}
|
||||
|
@ -893,9 +982,8 @@ static bool cs_add_command(
|
|||
) {
|
||||
ostd::Uint32 argmask = 0;
|
||||
int nargs = 0;
|
||||
ostd::ConstCharRange fmt(args);
|
||||
for (; !fmt.empty(); fmt.pop_front()) {
|
||||
switch (fmt.front()) {
|
||||
for (ostd::ConstCharRange fmt(args); !fmt.empty(); ++fmt) {
|
||||
switch (*fmt) {
|
||||
case 'i':
|
||||
case 'b':
|
||||
case 'f':
|
||||
|
@ -905,7 +993,9 @@ static bool cs_add_command(
|
|||
case 'E':
|
||||
case 'N':
|
||||
case 'D':
|
||||
if (nargs < MaxArguments) nargs++;
|
||||
if (nargs < MaxArguments) {
|
||||
nargs++;
|
||||
}
|
||||
break;
|
||||
case 'S':
|
||||
case 's':
|
||||
|
@ -921,15 +1011,18 @@ static bool cs_add_command(
|
|||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
if (nargs < MaxArguments)
|
||||
if (nargs < MaxArguments) {
|
||||
fmt.push_front_n(fmt.front() - '0' + 1);
|
||||
}
|
||||
break;
|
||||
case 'C':
|
||||
case 'V':
|
||||
break;
|
||||
default:
|
||||
ostd::err.writefln("builtin %s declared with illegal type: %c",
|
||||
name, fmt.front());
|
||||
ostd::err.writefln(
|
||||
"builtin %s declared with illegal type: %c",
|
||||
name, fmt.front()
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -948,11 +1041,13 @@ void cs_init_lib_io(CsState &cs) {
|
|||
auto file = args[0].get_strr();
|
||||
bool ret = cs.run_file(file);
|
||||
if (!ret) {
|
||||
if (args[1].get_int())
|
||||
if (args[1].get_int()) {
|
||||
ostd::err.writefln("could not run file \"%s\"", file);
|
||||
}
|
||||
res.set_int(0);
|
||||
} else
|
||||
} else {
|
||||
res.set_int(1);
|
||||
}
|
||||
});
|
||||
|
||||
cs_add_command(cs, "echo", "C", [](TvalRange args, TaggedValue &) {
|
||||
|
@ -979,14 +1074,19 @@ static inline void cs_set_iter(Ident &id, CsInt i, IdentStack &stack) {
|
|||
id.push_arg(v, stack);
|
||||
}
|
||||
|
||||
static inline void cs_do_loop(CsState &cs, Ident &id, CsInt offset, CsInt n,
|
||||
CsInt step, Bytecode *cond, Bytecode *body) {
|
||||
if (n <= 0 || (id.type != ID_ALIAS))
|
||||
static inline void cs_do_loop(
|
||||
CsState &cs, Ident &id, CsInt offset, CsInt n, CsInt step,
|
||||
Bytecode *cond, Bytecode *body
|
||||
) {
|
||||
if (n <= 0 || !id.is_alias()) {
|
||||
return;
|
||||
}
|
||||
IdentStack stack;
|
||||
for (CsInt i = 0; i < n; ++i) {
|
||||
cs_set_iter(id, offset + i * step, stack);
|
||||
if (cond && !cs.run_bool(cond)) break;
|
||||
if (cond && !cs.run_bool(cond)) {
|
||||
break;
|
||||
}
|
||||
cs.run_int(body);
|
||||
}
|
||||
id.pop_arg();
|
||||
|
@ -996,8 +1096,9 @@ static inline void cs_loop_conc(
|
|||
CsState &cs, TaggedValue &res, Ident &id, CsInt offset, CsInt n,
|
||||
CsInt step, Bytecode *body, bool space
|
||||
) {
|
||||
if (n <= 0 || id.type != ID_ALIAS)
|
||||
if (n <= 0 || !id.is_alias()) {
|
||||
return;
|
||||
}
|
||||
IdentStack stack;
|
||||
ostd::Vector<char> s;
|
||||
for (CsInt i = 0; i < n; ++i) {
|
||||
|
@ -1005,11 +1106,15 @@ static inline void cs_loop_conc(
|
|||
TaggedValue v;
|
||||
cs.run_ret(body, v);
|
||||
ostd::String vstr = ostd::move(v.get_str());
|
||||
if (space && i) s.push(' ');
|
||||
if (space && i) {
|
||||
s.push(' ');
|
||||
}
|
||||
s.push_n(vstr.data(), vstr.size());
|
||||
v.cleanup();
|
||||
}
|
||||
if (n > 0) id.pop_arg();
|
||||
if (n > 0) {
|
||||
id.pop_arg();
|
||||
}
|
||||
s.push('\0');
|
||||
ostd::Size len = s.size() - 1;
|
||||
res.set_mstr(ostd::CharRange(s.disown(), len));
|
||||
|
@ -1021,10 +1126,11 @@ void cs_init_lib_base(CsState &cs) {
|
|||
}, ID_DO);
|
||||
|
||||
cs_add_command(cs, "doargs", "e", [&cs](TvalRange args, TaggedValue &res) {
|
||||
if (cs.stack != &cs.noalias)
|
||||
if (cs.stack != &cs.noalias) {
|
||||
cs_do_args(cs, [&]() { cs.run_ret(args[0].get_code(), res); });
|
||||
else
|
||||
} else {
|
||||
cs.run_ret(args[0].get_code(), res);
|
||||
}
|
||||
}, ID_DOARGS);
|
||||
|
||||
cs_add_command(cs, "if", "tee", [&cs](TvalRange args, TaggedValue &res) {
|
||||
|
@ -1042,28 +1148,42 @@ void cs_init_lib_base(CsState &cs) {
|
|||
}, ID_NOT);
|
||||
|
||||
cs_add_command(cs, "&&", "E1V", [&cs](TvalRange args, TaggedValue &res) {
|
||||
if (args.empty())
|
||||
if (args.empty()) {
|
||||
res.set_int(1);
|
||||
else for (ostd::Size i = 0; i < args.size(); ++i) {
|
||||
if (i) res.cleanup();
|
||||
if (args[i].get_type() == VAL_CODE)
|
||||
} else {
|
||||
for (ostd::Size i = 0; i < args.size(); ++i) {
|
||||
if (i) {
|
||||
res.cleanup();
|
||||
}
|
||||
if (args[i].get_type() == VAL_CODE) {
|
||||
cs.run_ret(args[i].code, res);
|
||||
else
|
||||
} else {
|
||||
res = args[i];
|
||||
if (!res.get_bool()) break;
|
||||
}
|
||||
if (!res.get_bool()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, ID_AND);
|
||||
|
||||
cs_add_command(cs, "||", "E1V", [&cs](TvalRange args, TaggedValue &res) {
|
||||
if (args.empty())
|
||||
if (args.empty()) {
|
||||
res.set_int(0);
|
||||
else for (ostd::Size i = 0; i < args.size(); ++i) {
|
||||
if (i) res.cleanup();
|
||||
if (args[i].get_type() == VAL_CODE)
|
||||
} else {
|
||||
for (ostd::Size i = 0; i < args.size(); ++i) {
|
||||
if (i) {
|
||||
res.cleanup();
|
||||
}
|
||||
if (args[i].get_type() == VAL_CODE) {
|
||||
cs.run_ret(args[i].code, res);
|
||||
else
|
||||
} else {
|
||||
res = args[i];
|
||||
if (res.get_bool()) break;
|
||||
}
|
||||
if (res.get_bool()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, ID_OR);
|
||||
|
||||
|
@ -1085,38 +1205,43 @@ void cs_init_lib_base(CsState &cs) {
|
|||
}
|
||||
});
|
||||
|
||||
#define CS_CMD_CASE(name, fmt, type, acc, compare) \
|
||||
cs_add_command(cs, name, fmt "te2V", [&cs](TvalRange args, TaggedValue &res) { \
|
||||
type val = ostd::move(acc); \
|
||||
ostd::Size i; \
|
||||
for (i = 1; (i + 1) < args.size(); i += 2) { \
|
||||
if (compare) { \
|
||||
cs.run_ret(args[i + 1].code, res); \
|
||||
return; \
|
||||
} \
|
||||
} \
|
||||
cs_add_command(cs, "case", "ite2V", [&cs](TvalRange args, TaggedValue &res) {
|
||||
CsInt val = args[0].get_int();
|
||||
for (ostd::Size i = 1; (i + 1) < args.size(); i += 2) {
|
||||
if ((args[i].get_type() == VAL_NULL) || (args[i].get_int() == val)) {
|
||||
cs.run_ret(args[i + 1].code, res);
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
CS_CMD_CASE("case", "i", CsInt, args[0].get_int(),
|
||||
((args[i].get_type() == VAL_NULL) ||
|
||||
(args[i].get_int() == val)));
|
||||
cs_add_command(cs, "casef", "fte2V", [&cs](TvalRange args, TaggedValue &res) {
|
||||
CsFloat val = args[0].get_float();
|
||||
for (ostd::Size i = 1; (i + 1) < args.size(); i += 2) {
|
||||
if ((args[i].get_type() == VAL_NULL) || (args[i].get_float() == val)) {
|
||||
cs.run_ret(args[i + 1].code, res);
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
CS_CMD_CASE("casef", "f", CsFloat, args[0].get_float(),
|
||||
((args[i].get_type() == VAL_NULL) ||
|
||||
(args[i].get_float() == val)));
|
||||
|
||||
CS_CMD_CASE("cases", "s", ostd::String, args[0].get_str(),
|
||||
((args[i].get_type() == VAL_NULL) ||
|
||||
(args[i].get_str() == val)));
|
||||
|
||||
#undef CS_CMD_CASE
|
||||
cs_add_command(cs, "cases", "ste2V", [&cs](TvalRange args, TaggedValue &res) {
|
||||
ostd::String val = args[0].get_str();
|
||||
for (ostd::Size i = 1; (i + 1) < args.size(); i += 2) {
|
||||
if ((args[i].get_type() == VAL_NULL) || (args[i].get_str() == val)) {
|
||||
cs.run_ret(args[i + 1].code, res);
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
cs_add_command(cs, "pushif", "rTe", [&cs](TvalRange args, TaggedValue &res) {
|
||||
Ident *id = args[0].get_ident();
|
||||
TaggedValue &v = args[1];
|
||||
Bytecode *code = args[2].get_code();
|
||||
if ((id->type != ID_ALIAS) || (id->index < MaxArguments))
|
||||
if (!id->is_alias() || (id->index < MaxArguments)) {
|
||||
return;
|
||||
}
|
||||
if (v.get_bool()) {
|
||||
IdentStack stack;
|
||||
id->push_arg(v, stack);
|
||||
|
@ -1253,7 +1378,9 @@ void cs_init_lib_base(CsState &cs) {
|
|||
|
||||
cs_add_command(cs, "push", "rTe", [&cs](TvalRange args, TaggedValue &res) {
|
||||
Ident *id = args[0].get_ident();
|
||||
if (id->type != ID_ALIAS || id->index < MaxArguments) return;
|
||||
if (!id->is_alias() || (id->index < MaxArguments)) {
|
||||
return;
|
||||
}
|
||||
IdentStack stack;
|
||||
TaggedValue &v = args[1];
|
||||
id->push_arg(v, stack);
|
||||
|
@ -1301,10 +1428,18 @@ void cs_init_lib_string(CsState &cs);
|
|||
void cs_init_lib_list(CsState &cs);
|
||||
|
||||
OSTD_EXPORT void init_libs(CsState &cs, int libs) {
|
||||
if (libs & CS_LIB_IO ) cs_init_lib_io(cs);
|
||||
if (libs & CS_LIB_MATH ) cs_init_lib_math(cs);
|
||||
if (libs & CS_LIB_STRING) cs_init_lib_string(cs);
|
||||
if (libs & CS_LIB_LIST ) cs_init_lib_list(cs);
|
||||
if (libs & CS_LIB_IO) {
|
||||
cs_init_lib_io(cs);
|
||||
}
|
||||
if (libs & CS_LIB_MATH) {
|
||||
cs_init_lib_math(cs);
|
||||
}
|
||||
if (libs & CS_LIB_STRING) {
|
||||
cs_init_lib_string(cs);
|
||||
}
|
||||
if (libs & CS_LIB_LIST) {
|
||||
cs_init_lib_list(cs);
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace cscript */
|
||||
|
|
Loading…
Reference in New Issue