Fixed parsing of { objects } as expressions.
Fixed parsing of "var" declarations. Fixed indexing and fields of expressions. Small improvement to speed up the simplification of large code. git-svn-id: http://voip.null.ro/svn/yate@5146 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
306a64c041
commit
3dcef54cd1
|
@ -293,7 +293,7 @@ void ExpEvaluator::formatLineNo(String& buf, unsigned int line) const
|
|||
buf << "line " << line;
|
||||
}
|
||||
|
||||
bool ExpEvaluator::getInstruction(const char*& expr, GenObject* nested)
|
||||
bool ExpEvaluator::getInstruction(const char*& expr, char stop, GenObject* nested)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -590,7 +590,7 @@ bool ExpEvaluator::runCompile(const char*& expr, char stop, GenObject* nested)
|
|||
return true;
|
||||
}
|
||||
for (;;) {
|
||||
while (!stackPos && skipComments(expr) && getInstruction(expr,nested))
|
||||
while (!stackPos && skipComments(expr) && (*expr != stop) && getInstruction(expr,stop,nested))
|
||||
;
|
||||
if (inError())
|
||||
return false;
|
||||
|
@ -634,9 +634,15 @@ bool ExpEvaluator::trySimplify()
|
|||
{
|
||||
DDebug(this,DebugInfo,"trySimplify");
|
||||
bool done = false;
|
||||
for (unsigned int i = 0; i < m_opcodes.length(); i++) {
|
||||
for (unsigned int i = 0; ; i++) {
|
||||
ExpOperation* o = static_cast<ExpOperation*>(m_opcodes[i]);
|
||||
if (!o || o->barrier())
|
||||
if (!o) {
|
||||
if (i >= m_opcodes.length())
|
||||
break;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
if (o->barrier())
|
||||
continue;
|
||||
switch (o->opcode()) {
|
||||
case OpcLAnd:
|
||||
|
|
|
@ -152,7 +152,7 @@ protected:
|
|||
virtual int getKeyword(const char* str) const;
|
||||
virtual char skipComments(const char*& expr, GenObject* context = 0);
|
||||
virtual int preProcess(const char*& expr, GenObject* context = 0);
|
||||
virtual bool getInstruction(const char*& expr, GenObject* nested);
|
||||
virtual bool getInstruction(const char*& expr, char stop, GenObject* nested);
|
||||
virtual bool getSimple(const char*& expr, bool constOnly = false);
|
||||
virtual Opcode getOperator(const char*& expr);
|
||||
virtual Opcode getUnaryOperator(const char*& expr);
|
||||
|
@ -175,6 +175,7 @@ private:
|
|||
bool parseSwitch(const char*& expr, GenObject* nested);
|
||||
bool parseFor(const char*& expr, GenObject* nested);
|
||||
bool parseWhile(const char*& expr, GenObject* nested);
|
||||
bool parseVar(const char*& expr);
|
||||
bool parseTry(const char*& expr, GenObject* nested);
|
||||
bool parseFuncDef(const char*& expr, bool publish);
|
||||
bool evalList(ObjList& stack, GenObject* context) const;
|
||||
|
@ -882,7 +883,7 @@ bool JsCode::getOneInstruction(const char*& expr, GenObject* nested)
|
|||
return false;
|
||||
XDebug(this,DebugAll,"JsCode::getOneInstruction %p '%.30s'",nested,expr);
|
||||
if (skipComments(expr) == '{') {
|
||||
if (!getInstruction(expr,nested))
|
||||
if (!getInstruction(expr,0,nested))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
|
@ -894,12 +895,14 @@ bool JsCode::getOneInstruction(const char*& expr, GenObject* nested)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool JsCode::getInstruction(const char*& expr, GenObject* nested)
|
||||
bool JsCode::getInstruction(const char*& expr, char stop, GenObject* nested)
|
||||
{
|
||||
if (inError())
|
||||
return false;
|
||||
XDebug(this,DebugAll,"JsCode::getInstruction %p '%.30s'",nested,expr);
|
||||
XDebug(this,DebugAll,"JsCode::getInstruction %p '%.1s' '%.30s'",nested,&stop,expr);
|
||||
if (skipComments(expr) == '{') {
|
||||
if (stop == ')')
|
||||
return false;
|
||||
expr++;
|
||||
for (;;) {
|
||||
if (!runCompile(expr,'}',nested))
|
||||
|
@ -930,13 +933,15 @@ bool JsCode::getInstruction(const char*& expr, GenObject* nested)
|
|||
addOpcode(op);
|
||||
break;
|
||||
case OpcReturn:
|
||||
if (skipComments(expr) == ';')
|
||||
expr++;
|
||||
else {
|
||||
if (!runCompile(expr,';'))
|
||||
return false;
|
||||
if (skipComments(expr) == ';')
|
||||
expr++;
|
||||
switch (skipComments(expr)) {
|
||||
case ';':
|
||||
case '}':
|
||||
break;
|
||||
default:
|
||||
if (!runCompile(expr,';'))
|
||||
return false;
|
||||
if ((skipComments(expr) != ';') && (*expr != '}'))
|
||||
return gotError("Expecting ';' or '}'",expr);
|
||||
}
|
||||
addOpcode(op);
|
||||
break;
|
||||
|
@ -979,6 +984,8 @@ bool JsCode::getInstruction(const char*& expr, GenObject* nested)
|
|||
return gotError("Expecting ';'",expr);
|
||||
expr++;
|
||||
break;
|
||||
case OpcVar:
|
||||
return parseVar(expr);
|
||||
case OpcTry:
|
||||
return parseTry(expr,nested);
|
||||
case OpcFuncDef:
|
||||
|
@ -1100,6 +1107,7 @@ bool JsCode::parseIf(const char*& expr, GenObject* nested)
|
|||
if (skipComments(expr) != ')')
|
||||
return gotError("Expecting ')'",expr);
|
||||
ExpOperation* cond = addOpcode((Opcode)OpcJumpFalse,++m_label);
|
||||
expr++;
|
||||
if (!getOneInstruction(++expr,nested))
|
||||
return false;
|
||||
const char* save = expr;
|
||||
|
@ -1243,6 +1251,23 @@ bool JsCode::parseWhile(const char*& expr, GenObject* nested)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool JsCode::parseVar(const char*& expr)
|
||||
{
|
||||
if (inError())
|
||||
return false;
|
||||
XDebug(this,DebugAll,"parseVar '%.30s'",expr);
|
||||
skipComments(expr);
|
||||
int len = ExpEvaluator::getKeyword(expr);
|
||||
if (len <= 0 || expr[len] == '(')
|
||||
return gotError("Expecting variable name",expr);
|
||||
String str(expr,len);
|
||||
if (str.toInteger(s_instr,-1) >= 0 || str.toInteger(s_constants,-1) >= 0)
|
||||
return gotError("Not a valid variable name",expr);
|
||||
DDebug(this,DebugAll,"Found variable '%s'",str.safe());
|
||||
addOpcode((Opcode)OpcVar,str);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JsCode::parseTry(const char*& expr, GenObject* nested)
|
||||
{
|
||||
addOpcode((Opcode)OpcTry);
|
||||
|
@ -1599,6 +1624,15 @@ bool JsCode::runOperation(ObjList& stack, const ExpOperation& oper, GenObject* c
|
|||
return gotError("Stack underflow",oper.lineNumber());
|
||||
}
|
||||
if (op1->opcode() != OpcField) {
|
||||
ScriptContext* ctx = YOBJECT(ScriptContext,op1);
|
||||
if (ctx) {
|
||||
ExpOperation fld(OpcField,*op2);
|
||||
if (ctx->runField(stack,fld,context)) {
|
||||
TelEngine::destruct(op1);
|
||||
TelEngine::destruct(op2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
TelEngine::destruct(op1);
|
||||
TelEngine::destruct(op2);
|
||||
return gotError("Expecting field name",oper.lineNumber());
|
||||
|
@ -1617,7 +1651,18 @@ bool JsCode::runOperation(ObjList& stack, const ExpOperation& oper, GenObject* c
|
|||
TelEngine::destruct(op2);
|
||||
return gotError("Stack underflow",oper.lineNumber());
|
||||
}
|
||||
if (op1->opcode() != OpcField || op2->opcode() != OpcField) {
|
||||
if (op2->opcode() != OpcField) {
|
||||
TelEngine::destruct(op1);
|
||||
TelEngine::destruct(op2);
|
||||
return gotError("Expecting field names",oper.lineNumber());
|
||||
}
|
||||
if (op1->opcode() != OpcField) {
|
||||
ScriptContext* ctx = YOBJECT(ScriptContext,op1);
|
||||
if (ctx && ctx->runField(stack,*op2,context)) {
|
||||
TelEngine::destruct(op1);
|
||||
TelEngine::destruct(op2);
|
||||
break;
|
||||
}
|
||||
TelEngine::destruct(op1);
|
||||
TelEngine::destruct(op2);
|
||||
return gotError("Expecting field names",oper.lineNumber());
|
||||
|
@ -1653,6 +1698,21 @@ bool JsCode::runOperation(ObjList& stack, const ExpOperation& oper, GenObject* c
|
|||
TelEngine::destruct(op);
|
||||
}
|
||||
break;
|
||||
case OpcVar:
|
||||
{
|
||||
for (ObjList* l = stack.skipNull(); l; l = l->skipNext()) {
|
||||
JsObject* jso = YOBJECT(JsObject,l->get());
|
||||
if (jso && jso->toString() == YSTRING("()")) {
|
||||
if (!jso->hasField(stack,oper.name(),context)) {
|
||||
XDebug(this,DebugInfo,"Creating variable '%s' in scope",
|
||||
oper.name().c_str());
|
||||
jso->params().setParam(new ExpWrapper(0,oper.name()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OpcNew:
|
||||
{
|
||||
ExpOperation* op = popOne(stack);
|
||||
|
@ -1700,7 +1760,7 @@ bool JsCode::runOperation(ObjList& stack, const ExpOperation& oper, GenObject* c
|
|||
break;
|
||||
case OpcReturn:
|
||||
{
|
||||
ExpOperation* op = popOne(stack);
|
||||
ExpOperation* op = popValue(stack,context);
|
||||
bool ok = false;
|
||||
while (ExpOperation* drop = popAny(stack)) {
|
||||
ok = drop->opcode() == OpcFunc;
|
||||
|
|
|
@ -310,7 +310,7 @@ bool JsObject::runAssign(ObjList& stack, const ExpOperation& oper, GenObject* co
|
|||
XDebug(DebugAll,"JsObject::runAssign() '%s'='%s' in '%s' [%p]",
|
||||
oper.name().c_str(),oper.c_str(),toString().c_str(),this);
|
||||
if (frozen()) {
|
||||
Debug(DebugNote,"Object '%s' is frozen",toString().c_str());
|
||||
Debug(DebugWarn,"Object '%s' is frozen",toString().c_str());
|
||||
return false;
|
||||
}
|
||||
ExpFunction* ef = YOBJECT(ExpFunction,&oper);
|
||||
|
|
|
@ -570,10 +570,11 @@ protected:
|
|||
/**
|
||||
* Get an instruction or block, advance parsing pointer past it
|
||||
* @param expr Pointer to text to parse, gets advanced on success
|
||||
* @param stop Optional character expected after the instruction
|
||||
* @param nested User defined object passed from nested parsing
|
||||
* @return True if succeeded, must add the operands internally
|
||||
*/
|
||||
virtual bool getInstruction(const char*& expr, GenObject* nested = 0);
|
||||
virtual bool getInstruction(const char*& expr, char stop = 0, GenObject* nested = 0);
|
||||
|
||||
/**
|
||||
* Get an operand, advance parsing pointer past it
|
||||
|
|
|
@ -992,13 +992,25 @@ bool JsAssist::init()
|
|||
{
|
||||
if (!m_runner)
|
||||
return false;
|
||||
JsObject::initialize(m_runner->context());
|
||||
JsEngine::initialize(m_runner->context());
|
||||
JsChannel::initialize(m_runner->context(),this);
|
||||
JsMessage::initialize(m_runner->context());
|
||||
JsFile::initialize(m_runner->context());
|
||||
ScriptContext* ctx = m_runner->context();
|
||||
JsObject::initialize(ctx);
|
||||
JsEngine::initialize(ctx);
|
||||
JsChannel::initialize(ctx,this);
|
||||
JsMessage::initialize(ctx);
|
||||
JsFile::initialize(ctx);
|
||||
if (ScriptRun::Invalid == m_runner->reset())
|
||||
return false;
|
||||
ScriptContext* chan = YOBJECT(ScriptContext,ctx->getField(m_runner->stack(),YSTRING("Channel"),m_runner));
|
||||
if (chan) {
|
||||
JsMessage* jsm = YOBJECT(JsMessage,chan->getField(m_runner->stack(),YSTRING("message"),m_runner));
|
||||
if (!jsm) {
|
||||
jsm = new JsMessage(0,ctx->mutex(),false);
|
||||
ExpWrapper wrap(jsm,"message");
|
||||
chan->runAssign(m_runner->stack(),wrap,m_runner);
|
||||
}
|
||||
if (jsm && jsm->ref())
|
||||
ExpEvaluator::pushOne(m_runner->stack(),new ExpWrapper(jsm,"(message)"));
|
||||
}
|
||||
if (!m_runner->callable("onLoad"))
|
||||
return true;
|
||||
ScriptRun* runner = m_runner->code()->createRunner(m_runner->context());
|
||||
|
@ -1049,12 +1061,8 @@ bool JsAssist::setMsg(Message* msg)
|
|||
JsMessage* jsm = YOBJECT(JsMessage,chan->getField(stack,YSTRING("message"),m_runner));
|
||||
if (jsm)
|
||||
jsm->setMsg(msg,false);
|
||||
else {
|
||||
jsm = new JsMessage(msg,ctx->mutex(),false);
|
||||
ExpWrapper wrap(jsm,"message");
|
||||
if (!chan->runAssign(stack,wrap,m_runner))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
m_message = jsm;
|
||||
m_handled = false;
|
||||
return true;
|
||||
|
|
Loading…
Reference in New Issue