clean up Ident interface

master
Daniel Kolesa 2016-08-18 02:53:51 +01:00
parent f0f5fbc1ba
commit f3b3751f76
5 changed files with 232 additions and 176 deletions

126
cs_gen.cc
View File

@ -422,11 +422,11 @@ static void compilelookup(GenState &gs, int ltype, int prevargs = MaxResults) {
lookupid:
Ident *id = gs.cs.new_ident(lookup.get());
if (id) {
switch (id->type) {
case ID_IVAR:
switch (id->get_type()) {
case IdentType::ivar:
gs.code.push(
CODE_IVAR | cs_ret_code(ltype, RET_INT) |
(id->index << 8)
(id->get_index() << 8)
);
switch (ltype) {
case VAL_POP:
@ -440,10 +440,10 @@ lookupid:
break;
}
return;
case ID_FVAR:
case IdentType::fvar:
gs.code.push(
CODE_FVAR | cs_ret_code(ltype, RET_FLOAT) |
(id->index << 8)
(id->get_index() << 8)
);
switch (ltype) {
case VAL_POP:
@ -457,7 +457,7 @@ lookupid:
break;
}
return;
case ID_SVAR:
case IdentType::svar:
switch (ltype) {
case VAL_POP:
return;
@ -466,51 +466,53 @@ lookupid:
case VAL_CODE:
case VAL_IDENT:
case VAL_COND:
gs.code.push(CODE_SVARM | (id->index << 8));
gs.code.push(
CODE_SVARM | (id->get_index() << 8)
);
break;
default:
gs.code.push(
CODE_SVAR | cs_ret_code(ltype, RET_STR) |
(id->index << 8)
(id->get_index() << 8)
);
break;
}
goto done;
case ID_ALIAS:
case IdentType::alias:
switch (ltype) {
case VAL_POP:
return;
case VAL_CANY:
case VAL_COND:
gs.code.push(
(id->index < MaxArguments
(id->get_index() < MaxArguments
? CODE_LOOKUPMARG
: CODE_LOOKUPM
) | (id->index << 8)
) | (id->get_index() << 8)
);
break;
case VAL_CSTR:
case VAL_CODE:
case VAL_IDENT:
gs.code.push(
(id->index < MaxArguments
(id->get_index() < MaxArguments
? CODE_LOOKUPMARG
: CODE_LOOKUPM
) | RET_STR | (id->index << 8)
) | RET_STR | (id->get_index() << 8)
);
break;
default:
gs.code.push(
(id->index < MaxArguments
(id->get_index() < MaxArguments
? CODE_LOOKUPARG
: CODE_LOOKUP
) | cs_ret_code(ltype, RET_STR) |
(id->index << 8)
(id->get_index() << 8)
);
break;
}
goto done;
case ID_COMMAND: {
case IdentType::command: {
int comtype = CODE_COM, numargs = 0;
if (prevargs >= MaxResults) {
gs.code.push(CODE_ENTER);
@ -578,7 +580,7 @@ lookupid:
}
}
gs.code.push(
comtype | cs_ret_code(ltype) | (id->index << 8)
comtype | cs_ret_code(ltype) | (id->get_index() << 8)
);
gs.code.push(
(prevargs >= MaxResults
@ -590,7 +592,7 @@ lookupid:
compilecomv:
gs.code.push(
comtype | cs_ret_code(ltype) | (numargs << 8) |
(id->index << 13)
(id->get_index() << 13)
);
gs.code.push(
(prevargs >= MaxResults
@ -740,24 +742,26 @@ static bool compileblocksub(GenState &gs, int prevargs) {
lookupid:
Ident *id = gs.cs.new_ident(lookup.get());
if (id) {
switch (id->type) {
case ID_IVAR:
gs.code.push(CODE_IVAR | (id->index << 8));
switch (id->get_type()) {
case IdentType::ivar:
gs.code.push(CODE_IVAR | (id->get_index() << 8));
goto done;
case ID_FVAR:
gs.code.push(CODE_FVAR | (id->index << 8));
case IdentType::fvar:
gs.code.push(CODE_FVAR | (id->get_index() << 8));
goto done;
case ID_SVAR:
gs.code.push(CODE_SVARM | (id->index << 8));
case IdentType::svar:
gs.code.push(CODE_SVARM | (id->get_index() << 8));
goto done;
case ID_ALIAS:
case IdentType::alias:
gs.code.push(
(id->index < MaxArguments
(id->get_index() < MaxArguments
? CODE_LOOKUPMARG
: CODE_LOOKUPM
) | (id->index << 8)
) | (id->get_index() << 8)
);
goto done;
default:
break;
}
}
gs.gen_str(lookup.get(), true);
@ -1091,39 +1095,48 @@ static void compilestatements(GenState &gs, int rettype, int brak, int prevargs)
if (idname) {
Ident *id = gs.cs.new_ident(idname.get());
if (id) {
switch (id->type) {
case ID_ALIAS:
switch (id->get_type()) {
case IdentType::alias:
more = compilearg(gs, VAL_ANY, prevargs);
if (!more) {
gs.gen_str();
}
gs.code.push(
(id->index < MaxArguments
(id->get_index() < MaxArguments
? CODE_ALIASARG
: CODE_ALIAS) | (id->index << 8)
: CODE_ALIAS
) | (id->get_index() << 8)
);
goto endstatement;
case ID_IVAR:
case IdentType::ivar:
more = compilearg(gs, VAL_INT, prevargs);
if (!more) {
gs.gen_int();
}
gs.code.push(CODE_IVAR1 | (id->index << 8));
gs.code.push(
CODE_IVAR1 | (id->get_index() << 8)
);
goto endstatement;
case ID_FVAR:
case IdentType::fvar:
more = compilearg(gs, VAL_FLOAT, prevargs);
if (!more) {
gs.gen_float();
}
gs.code.push(CODE_FVAR1 | (id->index << 8));
gs.code.push(
CODE_FVAR1 | (id->get_index() << 8)
);
goto endstatement;
case ID_SVAR:
case IdentType::svar:
more = compilearg(gs, VAL_CSTR, prevargs);
if (!more) {
gs.gen_str();
}
gs.code.push(CODE_SVAR1 | (id->index << 8));
gs.code.push(
CODE_SVAR1 | (id->get_index() << 8)
);
goto endstatement;
default:
break;
}
}
gs.gen_str(idname.get(), true);
@ -1172,7 +1185,7 @@ noid:
}
gs.code.push(CODE_RESULT);
} else {
switch (id->type) {
switch (id->get_type_raw()) {
case ID_ALIAS:
while (numargs < MaxArguments) {
more = compilearg(gs, VAL_ANY, prevargs + numargs);
@ -1182,10 +1195,10 @@ noid:
++numargs;
}
gs.code.push(
(id->index < MaxArguments
(id->get_index() < MaxArguments
? CODE_CALLARG
: CODE_CALL
) | (numargs << 8) | (id->index << 13)
) | (numargs << 8) | (id->get_index() << 13)
);
break;
case ID_COMMAND: {
@ -1406,13 +1419,14 @@ noid:
}
}
gs.code.push(
comtype | cs_ret_code(rettype) | (id->index << 8)
comtype | cs_ret_code(rettype) |
(id->get_index() << 8)
);
break;
compilecomv:
gs.code.push(
comtype | cs_ret_code(rettype) | (numargs << 8) |
(id->index << 13)
(id->get_index() << 13)
);
break;
}
@ -1512,7 +1526,7 @@ compilecomv:
}
gs.code.push(
CODE_COM | cs_ret_code(rettype) |
(id->index << 8)
(id->get_index() << 8)
);
}
}
@ -1541,7 +1555,7 @@ compilecomv:
}
if (!more) {
gs.code.push(
(id->type == ID_AND
((id->get_type_raw() == ID_AND)
? CODE_TRUE
: CODE_FALSE
) | cs_ret_code(rettype)
@ -1580,10 +1594,10 @@ compilecomv:
}
gs.code.push(
CODE_COMV | cs_ret_code(rettype) |
(numargs << 8) | (id->index << 13)
(numargs << 8) | (id->get_index() << 13)
);
} else {
ostd::Uint32 op = id->type == ID_AND
ostd::Uint32 op = (id->get_type_raw() == ID_AND)
? CODE_JUMP_RESULT_FALSE
: CODE_JUMP_RESULT_TRUE;
gs.code.push(op);
@ -1604,29 +1618,29 @@ compilecomv:
break;
case ID_IVAR:
if (!(more = compilearg(gs, VAL_INT, prevargs))) {
gs.code.push(CODE_PRINT | (id->index << 8));
} else if (!(id->flags & IDF_HEX) || !(
gs.code.push(CODE_PRINT | (id->get_index() << 8));
} else if (!(id->get_flags() & IDF_HEX) || !(
more = compilearg(gs, VAL_INT, prevargs + 1)
)) {
gs.code.push(CODE_IVAR1 | (id->index << 8));
gs.code.push(CODE_IVAR1 | (id->get_index() << 8));
} else if (!(
more = compilearg(gs, VAL_INT, prevargs + 2)
)) {
gs.code.push(CODE_IVAR2 | (id->index << 8));
gs.code.push(CODE_IVAR2 | (id->get_index() << 8));
} else {
gs.code.push(CODE_IVAR3 | (id->index << 8));
gs.code.push(CODE_IVAR3 | (id->get_index() << 8));
}
break;
case ID_FVAR:
if (!(more = compilearg(gs, VAL_FLOAT, prevargs))) {
gs.code.push(CODE_PRINT | (id->index << 8));
gs.code.push(CODE_PRINT | (id->get_index() << 8));
} else {
gs.code.push(CODE_FVAR1 | (id->index << 8));
gs.code.push(CODE_FVAR1 | (id->get_index() << 8));
}
break;
case ID_SVAR:
if (!(more = compilearg(gs, VAL_CSTR, prevargs))) {
gs.code.push(CODE_PRINT | (id->index << 8));
gs.code.push(CODE_PRINT | (id->get_index() << 8));
} else {
do {
++numargs;
@ -1638,7 +1652,7 @@ compilecomv:
if (numargs > 1) {
gs.code.push(CODE_CONC | RET_STR | (numargs << 8));
}
gs.code.push(CODE_SVAR1 | (id->index << 8));
gs.code.push(CODE_SVAR1 | (id->get_index() << 8));
}
break;
}

View File

@ -7,7 +7,7 @@
namespace cscript {
static inline bool cs_has_cmd_cb(Ident *id) {
if ((id->type != ID_COMMAND) && (id->type < ID_LOCAL)) {
if (!id->is_command() && !id->is_special()) {
return false;
}
Command *cb = static_cast<Command *>(id);
@ -15,13 +15,13 @@ static inline bool cs_has_cmd_cb(Ident *id) {
}
static inline void cs_push_alias(Ident *id, IdentStack &st) {
if ((id->type == ID_ALIAS) && (id->index >= MaxArguments)) {
if (id->is_alias() && (id->get_index() >= MaxArguments)) {
static_cast<Alias *>(id)->push_arg(null_value, st);
}
}
static inline void cs_pop_alias(Ident *id) {
if ((id->type == ID_ALIAS) && (id->index >= MaxArguments)) {
if (id->is_alias() && (id->get_index() >= MaxArguments)) {
static_cast<Alias *>(id)->pop_arg();
}
}
@ -72,11 +72,11 @@ void cs_debug_alias(CsState &cs) {
Ident *id = l->id;
++depth;
if (depth < cs.dbgalias) {
ostd::err.writefln(" %d) %s", total - depth + 1, id->name);
ostd::err.writefln(" %d) %s", total - depth + 1, id->get_name());
} else if (l->next == &cs.noalias) {
ostd::err.writefln(
depth == cs.dbgalias ? " %d) %s" : " ..%d) %s",
total - depth + 1, id->name
total - depth + 1, id->get_name()
);
}
}
@ -458,7 +458,7 @@ static inline void cs_call_alias(
int oldargs = cs.numargs;
cs.numargs = callargs;
int oldflags = cs.identflags;
cs.identflags |= a->flags&IDF_OVERRIDDEN;
cs.identflags |= a->get_flags()&IDF_OVERRIDDEN;
IdentLink aliaslink = {
a, cs.stack, (1<<callargs)-1, argstack
};
@ -494,15 +494,15 @@ static thread_local int rundepth = 0;
static inline Alias *cs_get_lookup_id(CsState &cs, ostd::Uint32 op) {
Ident *id = cs.identmap[op >> 8];
if (id->flags & IDF_UNKNOWN) {
cs_debug_code(cs, "unknown alias lookup: %s", id->name);
if (id->get_flags() & IDF_UNKNOWN) {
cs_debug_code(cs, "unknown alias lookup: %s", id->get_name());
}
return static_cast<Alias *>(id);
}
static inline Alias *cs_get_lookuparg_id(CsState &cs, ostd::Uint32 op) {
Ident *id = cs.identmap[op >> 8];
if (!(cs.stack->usedargs&(1<<id->index))) {
if (!(cs.stack->usedargs & (1 << id->get_index()))) {
return nullptr;
}
return static_cast<Alias *>(id);
@ -520,29 +520,29 @@ static inline int cs_get_lookupu_type(
}
id = cs.get_ident(arg.s);
if (id) {
switch(id->type) {
case ID_ALIAS:
if (id->flags & IDF_UNKNOWN) {
switch(id->get_type()) {
case IdentType::alias:
if (id->get_flags() & IDF_UNKNOWN) {
break;
}
arg.cleanup();
if (
(id->index < MaxArguments) &&
!(cs.stack->usedargs & (1 << id->index))
(id->get_index() < MaxArguments) &&
!(cs.stack->usedargs & (1 << id->get_index()))
) {
return ID_UNKNOWN;
}
return ID_ALIAS;
case ID_SVAR:
case IdentType::svar:
arg.cleanup();
return ID_SVAR;
case ID_IVAR:
case IdentType::ivar:
arg.cleanup();
return ID_IVAR;
case ID_FVAR:
case IdentType::fvar:
arg.cleanup();
return ID_FVAR;
case ID_COMMAND: {
case IdentType::command: {
arg.cleanup();
arg.set_null();
TaggedValue buf[MaxArguments];
@ -940,9 +940,11 @@ static ostd::Uint32 const *runcode(
continue;
case CODE_IDENTARG: {
Alias *a = static_cast<Alias *>(cs.identmap[op >> 8]);
if (!(cs.stack->usedargs & (1 << a->index))) {
a->push_arg(null_value, cs.stack->argstack[a->index], false);
cs.stack->usedargs |= 1 << a->index;
if (!(cs.stack->usedargs & (1 << a->get_index()))) {
a->push_arg(
null_value, cs.stack->argstack[a->get_index()], false
);
cs.stack->usedargs |= 1 << a->get_index();
}
args[numargs++].set_ident(a);
continue;
@ -957,11 +959,14 @@ static ostd::Uint32 const *runcode(
) {
id = cs.new_ident(ostd::ConstCharRange(arg.cstr, arg.len));
}
if (id->index < MaxArguments && !(cs.stack->usedargs & (1 << id->index))) {
if (
id->get_index() < MaxArguments &&
!(cs.stack->usedargs & (1 << id->get_index()))
) {
static_cast<Alias *>(id)->push_arg(
null_value, cs.stack->argstack[id->index], false
null_value, cs.stack->argstack[id->get_index()], false
);
cs.stack->usedargs |= 1 << id->index;
cs.stack->usedargs |= 1 << id->get_index();
}
arg.cleanup();
arg.set_ident(id);
@ -1397,8 +1402,8 @@ static ostd::Uint32 const *runcode(
result.force_null();
Ident *id = cs.identmap[op >> 13];
int callargs = (op >> 8) & 0x1F, offset = numargs - callargs;
if (id->flags & IDF_UNKNOWN) {
cs_debug_code(cs, "unknown command: %s", id->name);
if (id->get_flags() & IDF_UNKNOWN) {
cs_debug_code(cs, "unknown command: %s", id->get_name());
free_args(args, numargs, offset);
force_arg(result, op & CODE_RET_MASK);
continue;
@ -1416,7 +1421,7 @@ static ostd::Uint32 const *runcode(
result.force_null();
Ident *id = cs.identmap[op >> 13];
int callargs = (op >> 8) & 0x1F, offset = numargs - callargs;
if (!(cs.stack->usedargs & (1 << id->index))) {
if (!(cs.stack->usedargs & (1 << id->get_index()))) {
free_args(args, numargs, offset);
force_arg(result, op & CODE_RET_MASK);
continue;
@ -1461,7 +1466,7 @@ noid:
continue;
}
result.force_null();
switch (id->type) {
switch (id->get_type_raw()) {
default:
if (!cs_has_cmd_cb(id)) {
free_args(args, numargs, offset - 1);
@ -1531,8 +1536,8 @@ noid:
case ID_ALIAS: {
Alias *a = static_cast<Alias *>(id);
if (
a->index < MaxArguments &&
!(cs.stack->usedargs & (1 << a->index))
a->get_index() < MaxArguments &&
!(cs.stack->usedargs & (1 << a->get_index()))
) {
free_args(args, numargs, offset - 1);
force_arg(result, op & CODE_RET_MASK);
@ -1572,7 +1577,6 @@ void CsState::run_ret(ostd::ConstCharRange code, TaggedValue &ret) {
}
}
/* TODO */
void CsState::run_ret(Ident *id, TvalRange args, TaggedValue &ret) {
int nargs = int(args.size());
ret.set_null();
@ -1580,13 +1584,13 @@ void CsState::run_ret(Ident *id, TvalRange args, TaggedValue &ret) {
if (rundepth > MaxRunDepth) {
cs_debug_code(*this, "exceeded recursion limit");
} else if (id) {
switch (id->type) {
switch (id->get_type()) {
default:
if (!cs_has_cmd_cb(id)) {
break;
}
/* fallthrough */
case ID_COMMAND:
case IdentType::command:
if (nargs < static_cast<Command *>(id)->numargs) {
TaggedValue buf[MaxArguments];
memcpy(buf, args.data(), args.size() * sizeof(TaggedValue));
@ -1602,14 +1606,14 @@ void CsState::run_ret(Ident *id, TvalRange args, TaggedValue &ret) {
}
nargs = 0;
break;
case ID_IVAR:
case IdentType::ivar:
if (args.empty()) {
print_var(static_cast<Ivar *>(id));
} else {
set_var_int_checked(static_cast<Ivar *>(id), args);
}
break;
case ID_FVAR:
case IdentType::fvar:
if (args.empty()) {
print_var(static_cast<Fvar *>(id));
} else {
@ -1618,7 +1622,7 @@ void CsState::run_ret(Ident *id, TvalRange args, TaggedValue &ret) {
);
}
break;
case ID_SVAR:
case IdentType::svar:
if (args.empty()) {
print_var(static_cast<Svar *>(id));
} else {
@ -1627,10 +1631,10 @@ void CsState::run_ret(Ident *id, TvalRange args, TaggedValue &ret) {
);
}
break;
case ID_ALIAS: {
case IdentType::alias: {
Alias *a = static_cast<Alias *>(id);
if (a->index < MaxArguments) {
if (!(stack->usedargs & (1 << a->index))) {
if (a->get_index() < MaxArguments) {
if (!(stack->usedargs & (1 << a->get_index()))) {
break;
}
}

View File

@ -205,10 +205,10 @@ struct GenState {
void gen_ident(Ident *id) {
code.push(
((id->index < MaxArguments)
((id->get_index() < MaxArguments)
? CODE_IDENTARG
: CODE_IDENT
) | (id->index << 8)
) | (id->get_index() << 8)
);
}

View File

@ -39,7 +39,7 @@ bool cs_check_num(ostd::ConstCharRange s) {
}
Ident::Ident(IdentType tp, ostd::ConstCharRange nm, int fl):
type(int(tp)), flags(fl), name(nm)
p_name(nm), p_type(int(tp)), p_flags(fl)
{}
Var::Var(IdentType tp, ostd::ConstCharRange name, VarCb f, int fl):
@ -98,11 +98,11 @@ Command::Command(
int tp, ostd::ConstCharRange name, ostd::ConstCharRange args,
ostd::Uint32 amask, int nargs, CmdFunc f
):
Ident(IdentType::unknown, name, 0),
Ident(IdentType::command, name, 0),
cargs(!args.empty() ? cs_dup_ostr(args) : nullptr),
argmask(amask), numargs(nargs), cb_cftv(ostd::move(f))
{
type = tp;
p_type = tp;
}
bool Ident::is_alias() const {
@ -127,6 +127,10 @@ bool Ident::is_command() const {
return get_type() == IdentType::command;
}
bool Ident::is_special() const {
return get_type() == IdentType::special;
}
bool Ident::is_var() const {
IdentType tp = get_type();
return (tp >= IdentType::ivar) && (tp <= IdentType::svar);
@ -221,11 +225,11 @@ CsState::CsState() {
CsState::~CsState() {
for (auto &p: idents.iter()) {
Ident *i = p.second;
if (i->type == ID_ALIAS) {
Alias *a = static_cast<Alias *>(i);
Alias *a = i->get_alias();
if (a) {
a->force_null();
delete[] reinterpret_cast<ostd::Uint32 *>(a->code);
} else if (i->type == ID_COMMAND || i->type >= ID_LOCAL) {
} else if (i->is_command() || i->is_special()) {
delete[] static_cast<Command *>(i)->cargs;
}
delete i;
@ -233,38 +237,40 @@ CsState::~CsState() {
}
void CsState::clear_override(Ident &id) {
if (!(id.flags & IDF_OVERRIDDEN)) {
if (!(id.get_flags() & IDF_OVERRIDDEN)) {
return;
}
switch (id.type) {
case ID_ALIAS: {
switch (id.get_type()) {
case IdentType::alias: {
Alias &a = static_cast<Alias &>(id);
a.val_v.cleanup();
a.clean_code();
a.val_v.set_str("");
break;
}
case ID_IVAR: {
case IdentType::ivar: {
Ivar &iv = static_cast<Ivar &>(id);
*iv.storage = iv.overrideval;
iv.changed();
break;
}
case ID_FVAR: {
case IdentType::fvar: {
Fvar &fv = static_cast<Fvar &>(id);
*fv.storage = fv.overrideval;
fv.changed();
break;
}
case ID_SVAR: {
case IdentType::svar: {
Svar &sv = static_cast<Svar &>(id);
delete[] *sv.storage;
*sv.storage = sv.overrideval;
sv.changed();
break;
}
default:
break;
}
id.flags &= ~IDF_OVERRIDDEN;
id.p_flags &= ~IDF_OVERRIDDEN;
}
void CsState::clear_overrides() {
@ -273,6 +279,15 @@ void CsState::clear_overrides() {
}
}
Ident *CsState::add_ident(Ident *id) {
if (!id) {
return nullptr;
}
idents[id->get_name()] = id;
id->p_index = identmap.size();
return identmap.push(id);
}
Ident *CsState::new_ident(ostd::ConstCharRange name, int flags) {
Ident *id = get_ident(name);
if (!id) {
@ -314,8 +329,8 @@ bool CsState::reset_var(ostd::ConstCharRange name) {
if (!id) {
return false;
}
if (id->flags & IDF_READONLY) {
cs_debug_code(*this, "variable %s is read only", id->name);
if (id->get_flags() & IDF_READONLY) {
cs_debug_code(*this, "variable %s is read only", id->get_name());
return false;
}
clear_override(*id);
@ -332,28 +347,29 @@ void CsState::touch_var(ostd::ConstCharRange name) {
void CsState::set_alias(ostd::ConstCharRange name, TaggedValue &v) {
Ident *id = get_ident(name);
if (id) {
switch (id->type) {
case ID_ALIAS: {
switch (id->get_type()) {
case IdentType::alias: {
Alias *a = static_cast<Alias *>(id);
if (a->index < MaxArguments) {
if (a->get_index() < MaxArguments) {
a->set_arg(*this, v);
} else {
a->set_alias(*this, v);
}
return;
}
case ID_IVAR:
case IdentType::ivar:
set_var_int_checked(static_cast<Ivar *>(id), v.get_int());
break;
case ID_FVAR:
case IdentType::fvar:
set_var_float_checked(static_cast<Fvar *>(id), v.get_float());
break;
case ID_SVAR:
case IdentType::svar:
set_var_str_checked(static_cast<Svar *>(id), v.get_str());
break;
default:
cs_debug_code(
*this, "cannot redefine builtin %s with an alias", id->name
*this, "cannot redefine builtin %s with an alias",
id->get_name()
);
break;
}
@ -368,32 +384,32 @@ void CsState::set_alias(ostd::ConstCharRange name, TaggedValue &v) {
void CsState::print_var_int(Ivar *iv, CsInt i) {
if (i < 0) {
writefln("%s = %d", iv->name, i);
writefln("%s = %d", iv->get_name(), i);
return;
}
if (iv->flags & IDF_HEX) {
if (iv->get_flags() & IDF_HEX) {
if (iv->maxval == 0xFFFFFF) {
writefln(
"%s = 0x%.6X (%d, %d, %d)", iv->name,
"%s = 0x%.6X (%d, %d, %d)", iv->get_name(),
i, (i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF
);
} else {
writefln("%s = 0x%X", iv->name, i);
writefln("%s = 0x%X", iv->get_name(), i);
}
} else {
writefln("%s = %d", iv->name, i);
writefln("%s = %d", iv->get_name(), i);
}
}
void CsState::print_var_float(Fvar *fv, CsFloat f) {
writefln("%s = %s", fv->name, floatstr(f));
writefln("%s = %s", fv->get_name(), floatstr(f));
}
void CsState::print_var_str(Svar *sv, ostd::ConstCharRange s) {
if (ostd::find(s, '"').empty()) {
writefln("%s = \"%s\"", sv->name, s);
writefln("%s = \"%s\"", sv->get_name(), s);
} else {
writefln("%s = [%s]", sv->name, s);
writefln("%s = [%s]", sv->get_name(), s);
}
}
@ -695,7 +711,7 @@ void Alias::push_arg(TaggedValue const &v, IdentStack &st, bool um) {
set_value(v);
clean_code();
if (um) {
flags &= ~IDF_UNKNOWN;
p_flags &= ~IDF_UNKNOWN;
}
}
@ -728,13 +744,13 @@ void Alias::redo_arg(IdentStack const &st) {
}
void Alias::set_arg(CsState &cs, TaggedValue &v) {
if (cs.stack->usedargs & (1 << index)) {
if (cs.stack->usedargs & (1 << get_index())) {
val_v.cleanup();
set_value(v);
clean_code();
} else {
push_arg(v, cs.stack->argstack[index], false);
cs.stack->usedargs |= 1 << index;
push_arg(v, cs.stack->argstack[get_index()], false);
cs.stack->usedargs |= 1 << get_index();
}
}
@ -742,35 +758,49 @@ void Alias::set_alias(CsState &cs, TaggedValue &v) {
val_v.cleanup();
set_value(v);
clean_code();
flags = (flags & cs.identflags) | cs.identflags;
p_flags = (p_flags & cs.identflags) | cs.identflags;
}
IdentType Ident::get_type() const {
if (type > ID_ALIAS) {
return IdentType::unknown;
if (p_type > ID_ALIAS) {
return IdentType::special;
}
return IdentType(type);
return IdentType(p_type);
}
ostd::ConstCharRange Ident::get_name() const {
return p_name;
}
int Ident::get_flags() const {
return p_flags;
}
int Ident::get_index() const {
return p_index;
}
template<typename SF, typename RF, typename CF>
bool cs_override_var(CsState &cs, Var *v, SF sf, RF rf, CF cf) {
if ((cs.identflags & IDF_OVERRIDDEN) || (v->flags & IDF_OVERRIDE)) {
if (v->flags & IDF_PERSIST) {
static inline bool cs_override_var(
CsState &cs, Var *v, int &vflags, SF sf, RF rf, CF cf
) {
if ((cs.identflags & IDF_OVERRIDDEN) || (vflags & IDF_OVERRIDE)) {
if (vflags & IDF_PERSIST) {
cs_debug_code(
cs, "cannot override persistent variable '%s'", v->name
cs, "cannot override persistent variable '%s'", v->get_name()
);
return false;
}
if (!(v->flags & IDF_OVERRIDDEN)) {
if (!(vflags & IDF_OVERRIDDEN)) {
sf();
v->flags |= IDF_OVERRIDDEN;
vflags |= IDF_OVERRIDDEN;
} else {
cf();
}
} else {
if (v->flags & IDF_OVERRIDDEN) {
if (vflags & IDF_OVERRIDDEN) {
rf();
v->flags &= ~IDF_OVERRIDDEN;
vflags &= ~IDF_OVERRIDDEN;
}
cf();
}
@ -786,7 +816,7 @@ void CsState::set_var_int(
}
Ivar *iv = static_cast<Ivar *>(id);
bool success = cs_override_var(
*this, iv,
*this, iv, iv->p_flags,
[&iv]() { iv->overrideval = *iv->storage; },
[]() {}, []() {}
);
@ -812,7 +842,7 @@ void CsState::set_var_float(
}
Fvar *fv = static_cast<Fvar *>(id);
bool success = cs_override_var(
*this, fv,
*this, fv, fv->p_flags,
[&fv]() { fv->overrideval = *fv->storage; },
[]() {}, []() {}
);
@ -838,7 +868,7 @@ void CsState::set_var_str(
}
Svar *sv = static_cast<Svar *>(id);
bool success = cs_override_var(
*this, sv,
*this, sv, sv->p_flags,
[&sv]() { sv->overrideval = *sv->storage; },
[&sv]() { delete[] sv->overrideval; },
[&sv]() { delete[] *sv->storage; }
@ -914,7 +944,10 @@ CsState::get_alias_val(ostd::ConstCharRange name) {
if (!a) {
return ostd::nothing;
}
if ((a->index < MaxArguments) && !(stack->usedargs & (1 << a->index))) {
if (
(a->get_index() < MaxArguments) &&
!(stack->usedargs & (1 << a->get_index()))
) {
return ostd::nothing;
}
return ostd::move(a->val_v.get_str());
@ -930,25 +963,25 @@ CsInt cs_clamp_var(CsState &cs, Ivar *iv, CsInt v) {
}
cs_debug_code(
cs,
(iv->flags & IDF_HEX)
(iv->get_flags() & IDF_HEX)
? (
(iv->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",
iv->name, iv->minval, iv->maxval
iv->get_name(), iv->minval, iv->maxval
);
return v;
}
void CsState::set_var_int_checked(Ivar *iv, CsInt v) {
if (iv->flags & IDF_READONLY) {
cs_debug_code(*this, "variable '%s' is read only", iv->name);
if (iv->get_flags() & IDF_READONLY) {
cs_debug_code(*this, "variable '%s' is read only", iv->get_name());
return;
}
bool success = cs_override_var(
*this, iv,
*this, iv, iv->p_flags,
[&iv]() { iv->overrideval = *iv->storage; },
[]() {}, []() {}
);
@ -964,7 +997,7 @@ void CsState::set_var_int_checked(Ivar *iv, CsInt v) {
void CsState::set_var_int_checked(Ivar *iv, TvalRange args) {
CsInt v = args[0].force_int();
if ((iv->flags & IDF_HEX) && (args.size() > 1)) {
if ((iv->get_flags() & IDF_HEX) && (args.size() > 1)) {
v = (v << 16) | (args[1].force_int() << 8);
if (args.size() > 2) {
v |= args[2].force_int();
@ -989,12 +1022,12 @@ CsFloat cs_clamp_fvar(CsState &cs, Fvar *fv, CsFloat v) {
}
void CsState::set_var_float_checked(Fvar *fv, CsFloat v) {
if (fv->flags & IDF_READONLY) {
cs_debug_code(*this, "variable '%s' is read only", fv->name);
if (fv->get_flags() & IDF_READONLY) {
cs_debug_code(*this, "variable '%s' is read only", fv->get_name());
return;
}
bool success = cs_override_var(
*this, fv,
*this, fv, fv->p_flags,
[&fv]() { fv->overrideval = *fv->storage; },
[]() {}, []() {}
);
@ -1009,12 +1042,12 @@ void CsState::set_var_float_checked(Fvar *fv, CsFloat v) {
}
void CsState::set_var_str_checked(Svar *sv, ostd::ConstCharRange v) {
if (sv->flags & IDF_READONLY) {
cs_debug_code(*this, "variable '%s' is read only", sv->name);
if (sv->get_flags() & IDF_READONLY) {
cs_debug_code(*this, "variable '%s' is read only", sv->get_name());
return;
}
bool success = cs_override_var(
*this, sv,
*this, sv, sv->p_flags,
[&sv]() { sv->overrideval = *sv->storage; },
[&sv]() { delete[] sv->overrideval; },
[&sv]() { delete[] *sv->storage; }
@ -1283,7 +1316,7 @@ void cs_init_lib_base(CsState &cs) {
Ident *id = args[0].get_ident();
TaggedValue &v = args[1];
Bytecode *code = args[2].get_code();
if (!id->is_alias() || (id->index < MaxArguments)) {
if (!id->is_alias() || (id->get_index() < MaxArguments)) {
return;
}
Alias *a = static_cast<Alias *>(id);
@ -1423,7 +1456,7 @@ 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->is_alias() || (id->index < MaxArguments)) {
if (!id->is_alias() || (id->get_index() < MaxArguments)) {
return;
}
Alias *a = static_cast<Alias *>(id);

View File

@ -168,8 +168,7 @@ struct IdentStack {
struct CsState;
enum class IdentType {
unknown = -1,
ivar, fvar, svar, command, alias
ivar = 0, fvar, svar, command, alias, special
};
struct Var;
@ -179,18 +178,19 @@ struct Svar;
struct Alias;
struct OSTD_EXPORT Ident {
int type; /* ID_something */
ostd::ushort flags;
int index = -1;
ostd::String name;
friend struct CsState;
IdentType get_type() const;
ostd::ConstCharRange get_name() const;
int get_flags() const;
int get_index() const;
bool is_alias() const;
Alias *get_alias();
Alias const *get_alias() const;
bool is_command() const;
bool is_special() const;
bool is_var() const;
Var *get_var();
@ -208,8 +208,21 @@ struct OSTD_EXPORT Ident {
Svar *get_svar();
Svar const *get_svar() const;
int get_type_raw() const {
return p_type;
}
protected:
Ident(IdentType tp, ostd::ConstCharRange name, int flags = 0);
ostd::String p_name;
/* represents the IdentType above, but internally it has a wider variety
* of values, so it's an int here (maps to an internal enum)
*/
int p_type, p_flags;
private:
int p_index = -1;
};
using VarCb = ostd::Function<void(Ident &)>;
@ -327,15 +340,7 @@ struct OSTD_EXPORT CsState {
void clear_override(Ident &id);
void clear_overrides();
Ident *add_ident(Ident *id) {
if (!id) {
return nullptr;
}
idents[id->name] = id;
id->index = identmap.size();
return identmap.push(id);
}
Ident *add_ident(Ident *id);
Ident *new_ident(ostd::ConstCharRange name, int flags = IDF_UNKNOWN);
Ident *force_ident(TaggedValue &v);