forked from OctaForge/libcubescript
make the arg/code APIs for CsAlias purely internal
parent
b687bd6016
commit
25894b469e
21
cs_gen.cc
21
cs_gen.cc
|
@ -1701,25 +1701,4 @@ void GenState::gen_main(ostd::ConstCharRange s, int ret_type) {
|
|||
code.push(CODE_EXIT | ((ret_type < VAL_ANY) ? (ret_type << CODE_RET) : 0));
|
||||
}
|
||||
|
||||
void CsAlias::clean_code() {
|
||||
ostd::Uint32 *bcode = reinterpret_cast<ostd::Uint32 *>(p_acode);
|
||||
if (bcode) {
|
||||
bcode_decr(bcode);
|
||||
p_acode = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
CsBytecode *CsAlias::compile_code(CsState &cs) {
|
||||
if (!p_acode) {
|
||||
GenState gs(cs);
|
||||
gs.code.reserve(64);
|
||||
gs.gen_main(p_val.get_str());
|
||||
ostd::Uint32 *code = new ostd::Uint32[gs.code.size()];
|
||||
memcpy(code, gs.code.data(), gs.code.size() * sizeof(ostd::Uint32));
|
||||
bcode_incr(code);
|
||||
p_acode = reinterpret_cast<CsBytecode *>(code);
|
||||
}
|
||||
return p_acode;
|
||||
}
|
||||
|
||||
} /* namespace cscript */
|
97
cs_vm.cc
97
cs_vm.cc
|
@ -6,70 +6,6 @@
|
|||
|
||||
namespace cscript {
|
||||
|
||||
void CsAlias::push_arg(CsValue const &v, CsIdentStack &st, bool um) {
|
||||
if (p_astack == &st) {
|
||||
/* prevent cycles and unnecessary code elsewhere */
|
||||
p_val.cleanup();
|
||||
p_val = v;
|
||||
clean_code();
|
||||
return;
|
||||
}
|
||||
st.val_s = p_val;
|
||||
st.next = p_astack;
|
||||
p_astack = &st;
|
||||
p_val = v;
|
||||
clean_code();
|
||||
if (um) {
|
||||
p_flags &= ~IDF_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
void CsAlias::pop_arg() {
|
||||
if (!p_astack) {
|
||||
return;
|
||||
}
|
||||
CsIdentStack *st = p_astack;
|
||||
p_val.cleanup();
|
||||
p_val = p_astack->val_s;
|
||||
clean_code();
|
||||
p_astack = st->next;
|
||||
}
|
||||
|
||||
void CsAlias::undo_arg(CsIdentStack &st) {
|
||||
CsIdentStack *prev = p_astack;
|
||||
st.val_s = p_val;
|
||||
st.next = prev;
|
||||
p_astack = prev->next;
|
||||
p_val = prev->val_s;
|
||||
clean_code();
|
||||
}
|
||||
|
||||
void CsAlias::redo_arg(CsIdentStack const &st) {
|
||||
CsIdentStack *prev = st.next;
|
||||
prev->val_s = p_val;
|
||||
p_astack = prev;
|
||||
p_val = st.val_s;
|
||||
clean_code();
|
||||
}
|
||||
|
||||
void CsAlias::set_arg(CsState &cs, CsValue &v) {
|
||||
if (cs.p_stack->usedargs & (1 << get_index())) {
|
||||
p_val.cleanup();
|
||||
p_val = v;
|
||||
clean_code();
|
||||
} else {
|
||||
push_arg(v, cs.p_stack->argstack[get_index()], false);
|
||||
cs.p_stack->usedargs |= 1 << get_index();
|
||||
}
|
||||
}
|
||||
|
||||
void CsAlias::set_alias(CsState &cs, CsValue &v) {
|
||||
p_val.cleanup();
|
||||
p_val = v;
|
||||
clean_code();
|
||||
p_flags = (p_flags & cs.identflags) | cs.identflags;
|
||||
}
|
||||
|
||||
static inline bool cs_has_cmd_cb(CsIdent *id) {
|
||||
if (!id->is_command() && !id->is_special()) {
|
||||
return false;
|
||||
|
@ -80,13 +16,13 @@ static inline bool cs_has_cmd_cb(CsIdent *id) {
|
|||
|
||||
static inline void cs_push_alias(CsIdent *id, CsIdentStack &st) {
|
||||
if (id->is_alias() && (id->get_index() >= MaxArguments)) {
|
||||
static_cast<CsAlias *>(id)->push_arg(null_value, st);
|
||||
CsAliasInternal::push_arg(static_cast<CsAlias *>(id), null_value, st);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void cs_pop_alias(CsIdent *id) {
|
||||
if (id->is_alias() && (id->get_index() >= MaxArguments)) {
|
||||
static_cast<CsAlias *>(id)->pop_arg();
|
||||
CsAliasInternal::pop_arg(static_cast<CsAlias *>(id));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -521,7 +457,8 @@ static inline void cs_call_alias(
|
|||
CsIvar *anargs = static_cast<CsIvar *>(cs.identmap[NumargsIdx]);
|
||||
CsIdentStack argstack[MaxArguments];
|
||||
for(int i = 0; i < callargs; i++) {
|
||||
static_cast<CsAlias *>(cs.identmap[i])->push_arg(
|
||||
CsAliasInternal::push_arg(
|
||||
static_cast<CsAlias *>(cs.identmap[i]),
|
||||
args[offset + i], argstack[i], false
|
||||
);
|
||||
}
|
||||
|
@ -533,19 +470,23 @@ static inline void cs_call_alias(
|
|||
a, cs.p_stack, (1<<callargs)-1, argstack
|
||||
};
|
||||
cs.p_stack = &aliaslink;
|
||||
ostd::Uint32 *codep = reinterpret_cast<ostd::Uint32 *>(a->compile_code(cs));
|
||||
ostd::Uint32 *codep = reinterpret_cast<ostd::Uint32 *>(
|
||||
CsAliasInternal::compile_code(a, cs)
|
||||
);
|
||||
bcode_incr(codep);
|
||||
runcode(cs, codep+1, (result));
|
||||
bcode_decr(codep);
|
||||
cs.p_stack = aliaslink.next;
|
||||
cs.identflags = oldflags;
|
||||
for (int i = 0; i < callargs; i++) {
|
||||
static_cast<CsAlias *>(cs.identmap[i])->pop_arg();
|
||||
CsAliasInternal::pop_arg(static_cast<CsAlias *>(cs.identmap[i]));
|
||||
}
|
||||
int argmask = aliaslink.usedargs & (~0 << callargs);
|
||||
for (; argmask; ++callargs) {
|
||||
if (argmask & (1 << callargs)) {
|
||||
static_cast<CsAlias *>(cs.identmap[callargs])->pop_arg();
|
||||
CsAliasInternal::pop_arg(static_cast<CsAlias *>(
|
||||
cs.identmap[callargs])
|
||||
);
|
||||
argmask &= ~(1 << callargs);
|
||||
}
|
||||
}
|
||||
|
@ -1008,8 +949,9 @@ static ostd::Uint32 *runcode(CsState &cs, ostd::Uint32 *code, CsValue &result) {
|
|||
case CODE_IDENTARG: {
|
||||
CsAlias *a = static_cast<CsAlias *>(cs.identmap[op >> 8]);
|
||||
if (!(cs.p_stack->usedargs & (1 << a->get_index()))) {
|
||||
a->push_arg(
|
||||
null_value, cs.p_stack->argstack[a->get_index()], false
|
||||
CsAliasInternal::push_arg(
|
||||
a, null_value, cs.p_stack->argstack[a->get_index()],
|
||||
false
|
||||
);
|
||||
cs.p_stack->usedargs |= 1 << a->get_index();
|
||||
}
|
||||
|
@ -1030,8 +972,9 @@ static ostd::Uint32 *runcode(CsState &cs, ostd::Uint32 *code, CsValue &result) {
|
|||
id->get_index() < MaxArguments &&
|
||||
!(cs.p_stack->usedargs & (1 << id->get_index()))
|
||||
) {
|
||||
static_cast<CsAlias *>(id)->push_arg(
|
||||
null_value, cs.p_stack->argstack[id->get_index()], false
|
||||
CsAliasInternal::push_arg(
|
||||
static_cast<CsAlias *>(id), null_value,
|
||||
cs.p_stack->argstack[id->get_index()], false
|
||||
);
|
||||
cs.p_stack->usedargs |= 1 << id->get_index();
|
||||
}
|
||||
|
@ -1468,12 +1411,14 @@ static ostd::Uint32 *runcode(CsState &cs, ostd::Uint32 *code, CsValue &result) {
|
|||
}
|
||||
|
||||
case CODE_ALIAS:
|
||||
static_cast<CsAlias *>(cs.identmap[op >> 8])->set_alias(
|
||||
CsAliasInternal::set_alias(
|
||||
static_cast<CsAlias *>(cs.identmap[op >> 8]),
|
||||
cs, args[--numargs]
|
||||
);
|
||||
continue;
|
||||
case CODE_ALIASARG:
|
||||
static_cast<CsAlias *>(cs.identmap[op >> 8])->set_arg(
|
||||
CsAliasInternal::set_arg(
|
||||
static_cast<CsAlias *>(cs.identmap[op >> 8]),
|
||||
cs, args[--numargs]
|
||||
);
|
||||
continue;
|
||||
|
|
143
cs_vm.hh
143
cs_vm.hh
|
@ -83,31 +83,6 @@ struct NullValue: CsValue {
|
|||
NullValue() { set_null(); }
|
||||
} const null_value;
|
||||
|
||||
template<typename F>
|
||||
static void cs_do_args(CsState &cs, F body) {
|
||||
CsIdentStack argstack[MaxArguments];
|
||||
int argmask1 = cs.p_stack->usedargs;
|
||||
for (int i = 0; argmask1; argmask1 >>= 1, ++i) {
|
||||
if (argmask1 & 1) {
|
||||
static_cast<CsAlias *>(cs.identmap[i])->undo_arg(argstack[i]);
|
||||
}
|
||||
}
|
||||
CsIdentLink *prevstack = cs.p_stack->next;
|
||||
CsIdentLink aliaslink = {
|
||||
cs.p_stack->id, cs.p_stack, prevstack->usedargs, prevstack->argstack
|
||||
};
|
||||
cs.p_stack = &aliaslink;
|
||||
body();
|
||||
prevstack->usedargs = aliaslink.usedargs;
|
||||
cs.p_stack = aliaslink.next;
|
||||
int argmask2 = cs.p_stack->usedargs;
|
||||
for (int i = 0; argmask2; argmask2 >>= 1, ++i) {
|
||||
if (argmask2 & 1) {
|
||||
static_cast<CsAlias *>(cs.identmap[i])->redo_arg(argstack[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ostd::ConstCharRange cs_debug_line(
|
||||
ostd::ConstCharRange p, ostd::ConstCharRange fmt, ostd::CharRange buf
|
||||
);
|
||||
|
@ -255,6 +230,124 @@ static inline void bcode_decr(ostd::Uint32 *bc) {
|
|||
}
|
||||
}
|
||||
|
||||
struct CsAliasInternal {
|
||||
static void push_arg(
|
||||
CsAlias *a, CsValue const &v, CsIdentStack &st, bool um = true
|
||||
) {
|
||||
if (a->p_astack == &st) {
|
||||
/* prevent cycles and unnecessary code elsewhere */
|
||||
a->p_val.cleanup();
|
||||
a->p_val = v;
|
||||
clean_code(a);
|
||||
return;
|
||||
}
|
||||
st.val_s = a->p_val;
|
||||
st.next = a->p_astack;
|
||||
a->p_astack = &st;
|
||||
a->p_val = v;
|
||||
clean_code(a);
|
||||
if (um) {
|
||||
a->p_flags &= ~IDF_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static void pop_arg(CsAlias *a) {
|
||||
if (!a->p_astack) {
|
||||
return;
|
||||
}
|
||||
CsIdentStack *st = a->p_astack;
|
||||
a->p_val.cleanup();
|
||||
a->p_val = a->p_astack->val_s;
|
||||
clean_code(a);
|
||||
a->p_astack = st->next;
|
||||
}
|
||||
|
||||
static void undo_arg(CsAlias *a, CsIdentStack &st) {
|
||||
CsIdentStack *prev = a->p_astack;
|
||||
st.val_s = a->p_val;
|
||||
st.next = prev;
|
||||
a->p_astack = prev->next;
|
||||
a->p_val = prev->val_s;
|
||||
clean_code(a);
|
||||
}
|
||||
|
||||
static void redo_arg(CsAlias *a, CsIdentStack const &st) {
|
||||
CsIdentStack *prev = st.next;
|
||||
prev->val_s = a->p_val;
|
||||
a->p_astack = prev;
|
||||
a->p_val = st.val_s;
|
||||
clean_code(a);
|
||||
}
|
||||
|
||||
static void set_arg(CsAlias *a, CsState &cs, CsValue &v) {
|
||||
if (cs.p_stack->usedargs & (1 << a->get_index())) {
|
||||
a->p_val.cleanup();
|
||||
a->p_val = v;
|
||||
clean_code(a);
|
||||
} else {
|
||||
push_arg(a, v, cs.p_stack->argstack[a->get_index()], false);
|
||||
cs.p_stack->usedargs |= 1 << a->get_index();
|
||||
}
|
||||
}
|
||||
|
||||
static void set_alias(CsAlias *a, CsState &cs, CsValue &v) {
|
||||
a->p_val.cleanup();
|
||||
a->p_val = v;
|
||||
clean_code(a);
|
||||
a->p_flags = (a->p_flags & cs.identflags) | cs.identflags;
|
||||
}
|
||||
|
||||
static void clean_code(CsAlias *a) {
|
||||
ostd::Uint32 *bcode = reinterpret_cast<ostd::Uint32 *>(a->p_acode);
|
||||
if (bcode) {
|
||||
bcode_decr(bcode);
|
||||
a->p_acode = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static CsBytecode *compile_code(CsAlias *a, CsState &cs) {
|
||||
if (!a->p_acode) {
|
||||
GenState gs(cs);
|
||||
gs.code.reserve(64);
|
||||
gs.gen_main(a->get_value().get_str());
|
||||
ostd::Uint32 *code = new ostd::Uint32[gs.code.size()];
|
||||
memcpy(code, gs.code.data(), gs.code.size() * sizeof(ostd::Uint32));
|
||||
bcode_incr(code);
|
||||
a->p_acode = reinterpret_cast<CsBytecode *>(code);
|
||||
}
|
||||
return a->p_acode;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename F>
|
||||
static void cs_do_args(CsState &cs, F body) {
|
||||
CsIdentStack argstack[MaxArguments];
|
||||
int argmask1 = cs.p_stack->usedargs;
|
||||
for (int i = 0; argmask1; argmask1 >>= 1, ++i) {
|
||||
if (argmask1 & 1) {
|
||||
CsAliasInternal::undo_arg(
|
||||
static_cast<CsAlias *>(cs.identmap[i]), argstack[i]
|
||||
);
|
||||
}
|
||||
}
|
||||
CsIdentLink *prevstack = cs.p_stack->next;
|
||||
CsIdentLink aliaslink = {
|
||||
cs.p_stack->id, cs.p_stack, prevstack->usedargs, prevstack->argstack
|
||||
};
|
||||
cs.p_stack = &aliaslink;
|
||||
body();
|
||||
prevstack->usedargs = aliaslink.usedargs;
|
||||
cs.p_stack = aliaslink.next;
|
||||
int argmask2 = cs.p_stack->usedargs;
|
||||
for (int i = 0; argmask2; argmask2 >>= 1, ++i) {
|
||||
if (argmask2 & 1) {
|
||||
CsAliasInternal::redo_arg(
|
||||
static_cast<CsAlias *>(cs.identmap[i]), argstack[i]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace cscript */
|
||||
|
||||
#endif /* LIBCUBESCRIPT_CS_VM_HH */
|
||||
|
|
|
@ -343,7 +343,7 @@ CsState::~CsState() {
|
|||
CsAlias *a = i->get_alias();
|
||||
if (a) {
|
||||
a->get_value().force_null();
|
||||
a->clean_code();
|
||||
CsAliasInternal::clean_code(a);
|
||||
}
|
||||
delete i;
|
||||
}
|
||||
|
@ -381,7 +381,7 @@ void CsState::clear_override(CsIdent &id) {
|
|||
case CsIdentType::alias: {
|
||||
CsAlias &a = static_cast<CsAlias &>(id);
|
||||
a.get_value().cleanup();
|
||||
a.clean_code();
|
||||
CsAliasInternal::clean_code(&a);
|
||||
a.get_value().set_str("");
|
||||
break;
|
||||
}
|
||||
|
@ -505,9 +505,9 @@ void CsState::set_alias(ostd::ConstCharRange name, CsValue &v) {
|
|||
case CsIdentType::alias: {
|
||||
CsAlias *a = static_cast<CsAlias *>(id);
|
||||
if (a->get_index() < MaxArguments) {
|
||||
a->set_arg(*this, v);
|
||||
CsAliasInternal::set_arg(a, *this, v);
|
||||
} else {
|
||||
a->set_alias(*this, v);
|
||||
CsAliasInternal::set_alias(a, *this, v);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -949,6 +949,50 @@ int CsIdent::get_index() const {
|
|||
return p_index;
|
||||
}
|
||||
|
||||
CsStackedValue::CsStackedValue(CsIdent *id):
|
||||
CsValue(), p_a(nullptr), p_stack(), p_pushed(false)
|
||||
{
|
||||
set_alias(id);
|
||||
}
|
||||
|
||||
CsStackedValue::~CsStackedValue() {
|
||||
pop();
|
||||
}
|
||||
|
||||
bool CsStackedValue::set_alias(CsIdent *id) {
|
||||
if (!id || !id->is_alias()) {
|
||||
return false;
|
||||
}
|
||||
p_a = static_cast<CsAlias *>(id);
|
||||
return true;
|
||||
}
|
||||
|
||||
CsAlias *CsStackedValue::get_alias() const {
|
||||
return p_a;
|
||||
}
|
||||
|
||||
bool CsStackedValue::has_alias() const {
|
||||
return p_a != nullptr;
|
||||
}
|
||||
|
||||
bool CsStackedValue::push() {
|
||||
if (!p_a) {
|
||||
return false;
|
||||
}
|
||||
CsAliasInternal::push_arg(p_a, *this, p_stack);
|
||||
p_pushed = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CsStackedValue::pop() {
|
||||
if (!p_pushed || !p_a) {
|
||||
return false;
|
||||
}
|
||||
CsAliasInternal::pop_arg(p_a);
|
||||
p_pushed = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename SF>
|
||||
static inline bool cs_override_var(CsState &cs, CsVar *v, int &vflags, SF sf) {
|
||||
if ((cs.identflags & IDF_OVERRIDDEN) || (vflags & IDF_OVERRIDE)) {
|
||||
|
|
|
@ -257,6 +257,7 @@ private:
|
|||
|
||||
struct OSTD_EXPORT CsAlias: CsIdent {
|
||||
friend struct CsState;
|
||||
friend struct CsAliasInternal;
|
||||
|
||||
CsValue const &get_value() const {
|
||||
return p_val;
|
||||
|
@ -268,17 +269,6 @@ struct OSTD_EXPORT CsAlias: CsIdent {
|
|||
|
||||
void get_cstr(CsValue &v) const;
|
||||
void get_cval(CsValue &v) const;
|
||||
|
||||
/* TODO: make all these internal */
|
||||
void push_arg(CsValue const &v, CsIdentStack &st, bool um = true);
|
||||
void pop_arg();
|
||||
void undo_arg(CsIdentStack &st);
|
||||
void redo_arg(CsIdentStack const &st);
|
||||
void set_arg(CsState &cs, CsValue &v);
|
||||
void set_alias(CsState &cs, CsValue &v);
|
||||
void clean_code();
|
||||
CsBytecode *compile_code(CsState &cs);
|
||||
|
||||
private:
|
||||
CsAlias(ostd::ConstCharRange n, char *a, int flags);
|
||||
CsAlias(ostd::ConstCharRange n, CsInt a, int flags);
|
||||
|
@ -476,49 +466,15 @@ private:
|
|||
};
|
||||
|
||||
struct OSTD_EXPORT CsStackedValue: CsValue {
|
||||
CsStackedValue(CsIdent *id = nullptr):
|
||||
CsValue(), p_a(nullptr), p_stack(), p_pushed(false)
|
||||
{
|
||||
set_alias(id);
|
||||
}
|
||||
CsStackedValue(CsIdent *id = nullptr);
|
||||
~CsStackedValue();
|
||||
|
||||
~CsStackedValue() {
|
||||
pop();
|
||||
}
|
||||
bool set_alias(CsIdent *id);
|
||||
CsAlias *get_alias() const;
|
||||
bool has_alias() const;
|
||||
|
||||
bool set_alias(CsIdent *id) {
|
||||
if (!id || !id->is_alias()) {
|
||||
return false;
|
||||
}
|
||||
p_a = static_cast<CsAlias *>(id);
|
||||
return true;
|
||||
}
|
||||
|
||||
CsAlias *get_alias() const {
|
||||
return p_a;
|
||||
}
|
||||
|
||||
bool has_alias() const {
|
||||
return p_a != nullptr;
|
||||
}
|
||||
|
||||
bool push() {
|
||||
if (!p_a) {
|
||||
return false;
|
||||
}
|
||||
p_a->push_arg(*this, p_stack);
|
||||
p_pushed = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pop() {
|
||||
if (!p_pushed || !p_a) {
|
||||
return false;
|
||||
}
|
||||
p_a->pop_arg();
|
||||
p_pushed = false;
|
||||
return true;
|
||||
}
|
||||
bool push();
|
||||
bool pop();
|
||||
|
||||
private:
|
||||
CsAlias *p_a;
|
||||
|
|
Loading…
Reference in New Issue