more progress
parent
b38fd774b8
commit
c3aa112e21
252
command.cc
252
command.cc
|
@ -146,13 +146,13 @@ void CsState::set_alias(ostd::ConstCharRange name, TaggedValue &v) {
|
|||
else id->set_alias(*this, v);
|
||||
return;
|
||||
case ID_VAR:
|
||||
setvarchecked(id, v.get_int());
|
||||
set_var_int_checked(id, v.get_int());
|
||||
break;
|
||||
case ID_FVAR:
|
||||
setfvarchecked(id, v.get_float());
|
||||
set_var_float_checked(id, v.get_float());
|
||||
break;
|
||||
case ID_SVAR:
|
||||
setsvarchecked(id, v.get_str());
|
||||
set_var_str_checked(id, v.get_str());
|
||||
break;
|
||||
default:
|
||||
debug_code("cannot redefine builtin %s with an alias", id->name);
|
||||
|
@ -531,123 +531,89 @@ CsState::get_alias(ostd::ConstCharRange name) {
|
|||
return ostd::ConstCharRange(id->get_str());
|
||||
}
|
||||
|
||||
void init_lib_base(CsState &cs) {
|
||||
cs.add_command("nodebug", "e", [](CsState &cs, ostd::uint *body) {
|
||||
++cs.nodebug;
|
||||
executeret(body, *cs.result);
|
||||
--cs.nodebug;
|
||||
});
|
||||
|
||||
cs.add_command("push", "rTe", [](CsState &cs, Ident *id,
|
||||
TaggedValue *v, ostd::uint *code) {
|
||||
if (id->type != ID_ALIAS || id->index < MAX_ARGUMENTS) return;
|
||||
IdentStack stack;
|
||||
id->push_arg(*v, stack);
|
||||
v->type = VAL_NULL;
|
||||
id->flags &= ~IDF_UNKNOWN;
|
||||
executeret(code, *cs.result);
|
||||
id->pop_arg();
|
||||
});
|
||||
|
||||
cs.add_command("local", ostd::ConstCharRange(), nullptr, ID_LOCAL);
|
||||
|
||||
cs.add_command("resetvar", "s", [](CsState &cs, char *name) {
|
||||
cs.result->set_int(cs.reset_var(name));
|
||||
});
|
||||
|
||||
cs.add_command("alias", "sT", [](CsState &cs, const char *name,
|
||||
TaggedValue *v) {
|
||||
cs.set_alias(name, *v);
|
||||
v->type = VAL_NULL;
|
||||
});
|
||||
|
||||
cs.add_command("getvarmin", "s", [](CsState &cs, const char *name) {
|
||||
cs.result->set_int(cs.get_var_min_int(name).value_or(0));
|
||||
});
|
||||
cs.add_command("getvarmax", "s", [](CsState &cs, const char *name) {
|
||||
cs.result->set_int(cs.get_var_max_int(name).value_or(0));
|
||||
});
|
||||
cs.add_command("getfvarmin", "s", [](CsState &cs, const char *name) {
|
||||
cs.result->set_float(cs.get_var_min_float(name).value_or(0.0f));
|
||||
});
|
||||
cs.add_command("getfvarmax", "s", [](CsState &cs, const char *name) {
|
||||
cs.result->set_float(cs.get_var_max_float(name).value_or(0.0f));
|
||||
});
|
||||
|
||||
cs.add_command("identexists", "s", [](CsState &cs, const char *name) {
|
||||
cs.result->set_int(cs.have_ident(name));
|
||||
});
|
||||
|
||||
cs.add_command("getalias", "s", [](CsState &cs, const char *name) {
|
||||
result(cs.get_alias(name).value_or("").data());
|
||||
});
|
||||
int cs_clamp_var(CsState &cs, Ident *id, int v) {
|
||||
if (v < id->minval)
|
||||
v = id->minval;
|
||||
else if (v > id->maxval)
|
||||
v = id->maxval;
|
||||
else
|
||||
return v;
|
||||
cs.debug_code((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 %d..%d",
|
||||
id->name, id->minval, id->maxval);
|
||||
return v;
|
||||
}
|
||||
|
||||
int clampvar(Ident *id, int val) {
|
||||
if (val < id->minval) val = id->minval;
|
||||
else if (val > id->maxval) val = id->maxval;
|
||||
else return val;
|
||||
cstate.debug_code(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 %d..%d",
|
||||
id->name, id->minval, id->maxval);
|
||||
return val;
|
||||
}
|
||||
|
||||
void setvarchecked(Ident *id, int val) {
|
||||
if (id->flags & IDF_READONLY) cstate.debug_code("variable %s is read-only", id->name);
|
||||
else {
|
||||
bool success = cs_override_var(cstate, id,
|
||||
[&id]() { id->overrideval.i = *id->storage.i; },
|
||||
[]() {}, []() {});
|
||||
if (!success) return;
|
||||
if (val < id->minval || val > id->maxval) val = clampvar(id, val);
|
||||
*id->storage.i = val;
|
||||
id->changed(cstate);
|
||||
void CsState::set_var_int_checked(Ident *id, int v) {
|
||||
if (id->flags & IDF_READONLY) {
|
||||
debug_code("variable '%s' is read only", id->name);
|
||||
return;
|
||||
}
|
||||
bool success = cs_override_var(*this, id,
|
||||
[&id]() { id->overrideval.i = *id->storage.i; },
|
||||
[]() {}, []() {});
|
||||
if (!success)
|
||||
return;
|
||||
if (v < id->minval || v > id->maxval)
|
||||
v = cs_clamp_var(*this, id, v);
|
||||
*id->storage.i = v;
|
||||
id->changed(*this);
|
||||
}
|
||||
|
||||
static inline void setvarchecked(Ident *id, TaggedValue *args, int numargs) {
|
||||
int val = args[0].force_int();
|
||||
if (id->flags & IDF_HEX && numargs > 1) {
|
||||
val = (val << 16) | (args[1].force_int() << 8);
|
||||
if (numargs > 2) val |= args[2].force_int();
|
||||
void CsState::set_var_int_checked(Ident *id,
|
||||
ostd::PointerRange<TaggedValue> args) {
|
||||
int 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)
|
||||
v |= args[2].force_int();
|
||||
}
|
||||
setvarchecked(id, val);
|
||||
set_var_int_checked(id, v);
|
||||
}
|
||||
|
||||
float clampfvar(Ident *id, float val) {
|
||||
if (val < id->minvalf) val = id->minvalf;
|
||||
else if (val > id->maxvalf) val = id->maxvalf;
|
||||
else return val;
|
||||
cstate.debug_code("valid range for %s is %s..%s", id->name, floatstr(id->minvalf), floatstr(id->maxvalf));
|
||||
return val;
|
||||
float cs_clamp_fvar(CsState &cs, Ident *id, float v) {
|
||||
if (v < id->minvalf)
|
||||
v = id->minvalf;
|
||||
else if (v > id->maxvalf)
|
||||
v = id->maxvalf;
|
||||
else
|
||||
return v;
|
||||
cs.debug_code("valid range for '%s' is %s..%s", floatstr(id->minvalf),
|
||||
floatstr(id->maxvalf));
|
||||
return v;
|
||||
}
|
||||
|
||||
void setfvarchecked(Ident *id, float val) {
|
||||
if (id->flags & IDF_READONLY) cstate.debug_code("variable %s is read-only", id->name);
|
||||
else {
|
||||
bool success = cs_override_var(cstate, id,
|
||||
[&id]() { id->overrideval.f = *id->storage.f; },
|
||||
[]() {}, []() {});
|
||||
if (!success) return;
|
||||
if (val < id->minvalf || val > id->maxvalf) val = clampfvar(id, val);
|
||||
*id->storage.f = val;
|
||||
id->changed(cstate);
|
||||
void CsState::set_var_float_checked(Ident *id, float v) {
|
||||
if (id->flags & IDF_READONLY) {
|
||||
debug_code("variable '%s' is read only", id->name);
|
||||
return;
|
||||
}
|
||||
bool success = cs_override_var(*this, id,
|
||||
[&id]() { id->overrideval.f = *id->storage.f; },
|
||||
[]() {}, []() {});
|
||||
if (!success)
|
||||
return;
|
||||
if (v < id->minvalf || v > id->maxvalf)
|
||||
v = cs_clamp_fvar(*this, id, v);
|
||||
*id->storage.f = v;
|
||||
id->changed(*this);
|
||||
}
|
||||
|
||||
void setsvarchecked(Ident *id, const char *val) {
|
||||
if (id->flags & IDF_READONLY) cstate.debug_code("variable %s is read-only", id->name);
|
||||
else {
|
||||
bool success = cs_override_var(cstate, id,
|
||||
[&id]() { id->overrideval.s = *id->storage.s; },
|
||||
[&id]() { delete[] id->overrideval.s; },
|
||||
[&id]() { delete[] *id->storage.s; });
|
||||
if (!success) return;
|
||||
*id->storage.s = dup_ostr(val);
|
||||
id->changed(cstate);
|
||||
void CsState::set_var_str_checked(Ident *id, ostd::ConstCharRange v) {
|
||||
if (id->flags & IDF_READONLY) {
|
||||
debug_code("variable '%s' is read only", id->name);
|
||||
return;
|
||||
}
|
||||
bool success = cs_override_var(*this, id,
|
||||
[&id]() { id->overrideval.s = *id->storage.s; },
|
||||
[&id]() { delete[] id->overrideval.s; },
|
||||
[&id]() { delete[] *id->storage.s; });
|
||||
if (!success) return;
|
||||
*id->storage.s = dup_ostr(v);
|
||||
id->changed(*this);
|
||||
}
|
||||
|
||||
bool CsState::add_command(ostd::ConstCharRange name, ostd::ConstCharRange args,
|
||||
|
@ -709,6 +675,58 @@ bool addcommand(const char *name, IdentFunc fun, const char *args, int type) {
|
|||
return cstate.add_command(name, args, fun, type);
|
||||
}
|
||||
|
||||
void init_lib_base(CsState &cs) {
|
||||
cs.add_command("nodebug", "e", [](CsState &cs, ostd::uint *body) {
|
||||
++cs.nodebug;
|
||||
executeret(body, *cs.result);
|
||||
--cs.nodebug;
|
||||
});
|
||||
|
||||
cs.add_command("push", "rTe", [](CsState &cs, Ident *id,
|
||||
TaggedValue *v, ostd::uint *code) {
|
||||
if (id->type != ID_ALIAS || id->index < MAX_ARGUMENTS) return;
|
||||
IdentStack stack;
|
||||
id->push_arg(*v, stack);
|
||||
v->type = VAL_NULL;
|
||||
id->flags &= ~IDF_UNKNOWN;
|
||||
executeret(code, *cs.result);
|
||||
id->pop_arg();
|
||||
});
|
||||
|
||||
cs.add_command("local", ostd::ConstCharRange(), nullptr, ID_LOCAL);
|
||||
|
||||
cs.add_command("resetvar", "s", [](CsState &cs, char *name) {
|
||||
cs.result->set_int(cs.reset_var(name));
|
||||
});
|
||||
|
||||
cs.add_command("alias", "sT", [](CsState &cs, const char *name,
|
||||
TaggedValue *v) {
|
||||
cs.set_alias(name, *v);
|
||||
v->type = VAL_NULL;
|
||||
});
|
||||
|
||||
cs.add_command("getvarmin", "s", [](CsState &cs, const char *name) {
|
||||
cs.result->set_int(cs.get_var_min_int(name).value_or(0));
|
||||
});
|
||||
cs.add_command("getvarmax", "s", [](CsState &cs, const char *name) {
|
||||
cs.result->set_int(cs.get_var_max_int(name).value_or(0));
|
||||
});
|
||||
cs.add_command("getfvarmin", "s", [](CsState &cs, const char *name) {
|
||||
cs.result->set_float(cs.get_var_min_float(name).value_or(0.0f));
|
||||
});
|
||||
cs.add_command("getfvarmax", "s", [](CsState &cs, const char *name) {
|
||||
cs.result->set_float(cs.get_var_max_float(name).value_or(0.0f));
|
||||
});
|
||||
|
||||
cs.add_command("identexists", "s", [](CsState &cs, const char *name) {
|
||||
cs.result->set_int(cs.have_ident(name));
|
||||
});
|
||||
|
||||
cs.add_command("getalias", "s", [](CsState &cs, const char *name) {
|
||||
result(cs.get_alias(name).value_or("").data());
|
||||
});
|
||||
}
|
||||
|
||||
const char *parsestring(const char *p) {
|
||||
for (; *p; p++) switch (*p) {
|
||||
case '\r':
|
||||
|
@ -2722,7 +2740,7 @@ static const ostd::uint *runcode(const ostd::uint *code, TaggedValue &result) {
|
|||
args[numargs++].set_cstr(*cstate.identmap[op >> 8]->storage.s);
|
||||
continue;
|
||||
case CODE_SVAR1:
|
||||
setsvarchecked(cstate.identmap[op >> 8], args[--numargs].s);
|
||||
cstate.set_var_str_checked(cstate.identmap[op >> 8], args[--numargs].s);
|
||||
args[numargs].cleanup();
|
||||
continue;
|
||||
|
||||
|
@ -2737,15 +2755,15 @@ static const ostd::uint *runcode(const ostd::uint *code, TaggedValue &result) {
|
|||
args[numargs++].set_float(float(*cstate.identmap[op >> 8]->storage.i));
|
||||
continue;
|
||||
case CODE_IVAR1:
|
||||
setvarchecked(cstate.identmap[op >> 8], args[--numargs].i);
|
||||
cstate.set_var_int_checked(cstate.identmap[op >> 8], args[--numargs].i);
|
||||
continue;
|
||||
case CODE_IVAR2:
|
||||
numargs -= 2;
|
||||
setvarchecked(cstate.identmap[op >> 8], (args[numargs].i << 16) | (args[numargs + 1].i << 8));
|
||||
cstate.set_var_int_checked(cstate.identmap[op >> 8], (args[numargs].i << 16) | (args[numargs + 1].i << 8));
|
||||
continue;
|
||||
case CODE_IVAR3:
|
||||
numargs -= 3;
|
||||
setvarchecked(cstate.identmap[op >> 8], (args[numargs].i << 16) | (args[numargs + 1].i << 8) | args[numargs + 2].i);
|
||||
cstate.set_var_int_checked(cstate.identmap[op >> 8], (args[numargs].i << 16) | (args[numargs + 1].i << 8) | args[numargs + 2].i);
|
||||
continue;
|
||||
|
||||
case CODE_FVAR|RET_FLOAT:
|
||||
|
@ -2759,7 +2777,7 @@ static const ostd::uint *runcode(const ostd::uint *code, TaggedValue &result) {
|
|||
args[numargs++].set_int(int(*cstate.identmap[op >> 8]->storage.f));
|
||||
continue;
|
||||
case CODE_FVAR1:
|
||||
setfvarchecked(cstate.identmap[op >> 8], args[--numargs].f);
|
||||
cstate.set_var_float_checked(cstate.identmap[op >> 8], args[--numargs].f);
|
||||
continue;
|
||||
|
||||
#define OFFSETARG(n) offset+n
|
||||
|
@ -2950,15 +2968,15 @@ noid:
|
|||
}
|
||||
case ID_VAR:
|
||||
if (callargs <= 0) printvar(id);
|
||||
else setvarchecked(id, &args[offset], callargs);
|
||||
else cstate.set_var_int_checked(id, ostd::iter(&args[offset], callargs));
|
||||
FORCERESULT;
|
||||
case ID_FVAR:
|
||||
if (callargs <= 0) printvar(id);
|
||||
else setfvarchecked(id, args[offset].force_float());
|
||||
else cstate.set_var_float_checked(id, args[offset].force_float());
|
||||
FORCERESULT;
|
||||
case ID_SVAR:
|
||||
if (callargs <= 0) printvar(id);
|
||||
else setsvarchecked(id, args[offset].force_str());
|
||||
else cstate.set_var_str_checked(id, args[offset].force_str());
|
||||
FORCERESULT;
|
||||
case ID_ALIAS:
|
||||
if (id->index < MAX_ARGUMENTS && !(cstate.stack->usedargs & (1 << id->index))) FORCERESULT;
|
||||
|
@ -3009,15 +3027,15 @@ void executeret(Ident *id, TaggedValue *args, int numargs, TaggedValue &result)
|
|||
break;
|
||||
case ID_VAR:
|
||||
if (numargs <= 0) printvar(id);
|
||||
else setvarchecked(id, args, numargs);
|
||||
else cstate.set_var_int_checked(id, ostd::iter(args, numargs));
|
||||
break;
|
||||
case ID_FVAR:
|
||||
if (numargs <= 0) printvar(id);
|
||||
else setfvarchecked(id, args[0].force_float());
|
||||
else cstate.set_var_float_checked(id, args[0].force_float());
|
||||
break;
|
||||
case ID_SVAR:
|
||||
if (numargs <= 0) printvar(id);
|
||||
else setsvarchecked(id, args[0].force_str());
|
||||
else cstate.set_var_str_checked(id, args[0].force_str());
|
||||
break;
|
||||
case ID_ALIAS:
|
||||
if (id->index < MAX_ARGUMENTS && !(cstate.stack->usedargs & (1 << id->index))) break;
|
||||
|
|
|
@ -406,6 +406,11 @@ struct CsState {
|
|||
void set_var_str(ostd::ConstCharRange name, ostd::ConstCharRange v,
|
||||
bool dofunc = true);
|
||||
|
||||
void set_var_int_checked(Ident *id, int v);
|
||||
void set_var_int_checked(Ident *id, ostd::PointerRange<TaggedValue> args);
|
||||
void set_var_float_checked(Ident *id, float v);
|
||||
void set_var_str_checked(Ident *id, ostd::ConstCharRange v);
|
||||
|
||||
ostd::Maybe<int> get_var_int(ostd::ConstCharRange name);
|
||||
ostd::Maybe<float> get_var_float(ostd::ConstCharRange name);
|
||||
ostd::Maybe<ostd::String> get_var_str(ostd::ConstCharRange name);
|
||||
|
@ -554,9 +559,6 @@ inline void Ident::getcval(TaggedValue &v) const {
|
|||
}
|
||||
}
|
||||
|
||||
extern void setvarchecked(Ident *id, int val);
|
||||
extern void setfvarchecked(Ident *id, float val);
|
||||
extern void setsvarchecked(Ident *id, const char *val);
|
||||
extern bool addcommand(const char *name, IdentFunc fun, const char *narg, int type = ID_COMMAND);
|
||||
extern ostd::uint *compilecode(const char *p);
|
||||
extern void keepcode(ostd::uint *p);
|
||||
|
|
Loading…
Reference in New Issue