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

View File

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

View File

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

View File

@ -168,8 +168,7 @@ struct IdentStack {
struct CsState; struct CsState;
enum class IdentType { enum class IdentType {
unknown = -1, ivar = 0, fvar, svar, command, alias, special
ivar, fvar, svar, command, alias
}; };
struct Var; struct Var;
@ -179,18 +178,19 @@ struct Svar;
struct Alias; struct Alias;
struct OSTD_EXPORT Ident { struct OSTD_EXPORT Ident {
int type; /* ID_something */ friend struct CsState;
ostd::ushort flags;
int index = -1;
ostd::String name;
IdentType get_type() const; IdentType get_type() const;
ostd::ConstCharRange get_name() const;
int get_flags() const;
int get_index() const;
bool is_alias() const; bool is_alias() const;
Alias *get_alias(); Alias *get_alias();
Alias const *get_alias() const; Alias const *get_alias() const;
bool is_command() const; bool is_command() const;
bool is_special() const;
bool is_var() const; bool is_var() const;
Var *get_var(); Var *get_var();
@ -208,8 +208,21 @@ struct OSTD_EXPORT Ident {
Svar *get_svar(); Svar *get_svar();
Svar const *get_svar() const; Svar const *get_svar() const;
int get_type_raw() const {
return p_type;
}
protected: protected:
Ident(IdentType tp, ostd::ConstCharRange name, int flags = 0); 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 &)>; using VarCb = ostd::Function<void(Ident &)>;
@ -327,15 +340,7 @@ struct OSTD_EXPORT CsState {
void clear_override(Ident &id); void clear_override(Ident &id);
void clear_overrides(); void clear_overrides();
Ident *add_ident(Ident *id) { Ident *add_ident(Ident *id);
if (!id) {
return nullptr;
}
idents[id->name] = id;
id->index = identmap.size();
return identmap.push(id);
}
Ident *new_ident(ostd::ConstCharRange name, int flags = IDF_UNKNOWN); Ident *new_ident(ostd::ConstCharRange name, int flags = IDF_UNKNOWN);
Ident *force_ident(TaggedValue &v); Ident *force_ident(TaggedValue &v);