forked from OctaForge/libcubescript
clean up Ident interface
parent
f0f5fbc1ba
commit
f3b3751f76
126
cs_gen.cc
126
cs_gen.cc
|
@ -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;
|
||||
}
|
||||
|
|
82
cs_vm.cc
82
cs_vm.cc
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
4
cs_vm.hh
4
cs_vm.hh
|
@ -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)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
161
cubescript.cc
161
cubescript.cc
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue