Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed conditional functions for MT #10

Open
wants to merge 3 commits into
base: MT
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 78 additions & 38 deletions avs_core/core/parser/expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
#include "../internal.h"
#include <avs/win.h>
#include <cassert>
#include <vector>


class BreakStmtException
Expand Down Expand Up @@ -445,33 +444,41 @@ AVSValue ExpNot::Evaluate(IScriptEnvironment* env)
}


AVSValue ExpVariableReference::Evaluate(IScriptEnvironment* env)
AVSValue ExpVariableReference::Evaluate(IScriptEnvironment* env)
{
AVSValue result;
IScriptEnvironment2 *env2 = static_cast<IScriptEnvironment2*>(env);

// first look for a genuine variable
// Don't add a cache to this one, it's a Var
if (env2->GetVar(name, &result)) {
if (env2->GetVar(name, &result))
return result;
}
else {
// Swap order to match ::Call below -- Gavino Jan 2010

// next look for an argless function
if (!env2->Invoke(&result, name, AVSValue(0,0)))
// Try various function syntaxes.

// look for an argless function
if (env2->Invoke(&result, name, AVSValue(0, 0)))
return result;

AVSValue last;
if (env2->GetVar("last", &last))
{
// look for a single-arg function taking implicit "last"
if (env2->Invoke(&result, name, last))
return result;

// Per-frame syntax
if (frame_number >= 0)
{
// finally look for a single-arg function taking implicit "last"
AVSValue last;
if (!env2->GetVar("last", &last) || !env2->Invoke(&result, name, last))
{
env->ThrowError("I don't know what '%s' means.", name);
return 0;
}
// Try function starting with "n,clip". Only per-frame functions start with "ic".
AVSValue sargs[2] = { frame_number, last };
if (env2->Invoke(&result, name, AVSValue(sargs, 2)))
return result;
}
}

return result;
env->ThrowError("I don't know what '%s' means.", name);
return 0;
}


Expand All @@ -489,17 +496,18 @@ AVSValue ExpGlobalAssignment::Evaluate(IScriptEnvironment* env)
}


ExpFunctionCall::ExpFunctionCall( const char* _name, PExpression* _arg_exprs,
const char** _arg_expr_names, int _arg_expr_count, bool _oop_notation )
: name(_name), arg_expr_count(_arg_expr_count), oop_notation(_oop_notation)
ExpFunctionCall::ExpFunctionCall(const char* _name, PExpression* _arg_exprs,
const char** _arg_expr_names, int _arg_expr_count, bool _oop_notation, int _frame_number)
: name(_name), arg_expr_count(_arg_expr_count), oop_notation(_oop_notation), frame_number(_frame_number)
{
// arg_expr_names has 2 extra item at the beginning, for implicit "last" and for "current_frame"
arg_exprs = new PExpression[arg_expr_count];
// arg_expr_names has an extra elt at the beginning, for implicit "last"
arg_expr_names = new const char*[arg_expr_count+1];
arg_expr_names = new const char*[arg_expr_count+2];
arg_expr_names[0] = 0;
for (int i=0; i<arg_expr_count; ++i) {
arg_expr_names[1] = 0;
for (int i = 0; i<arg_expr_count; ++i) {
arg_exprs[i] = _arg_exprs[i];
arg_expr_names[i+1] = _arg_expr_names[i];
arg_expr_names[i+2] = _arg_expr_names[i];
}
}

Expand All @@ -514,25 +522,47 @@ AVSValue ExpFunctionCall::Evaluate(IScriptEnvironment* env)
AVSValue result;
IScriptEnvironment2 *env2 = static_cast<IScriptEnvironment2*>(env);

std::vector<AVSValue> args(arg_expr_count+1, AVSValue());
std::vector<AVSValue> args(arg_expr_count+2, AVSValue());
for (int a=0; a<arg_expr_count; ++a)
args[a+1] = arg_exprs[a]->Evaluate(env);

// first try without implicit "last"
try
{ // Invoke can always throw by calling a constructor of a filter that throws
if (env2->Invoke(&result, name, AVSValue(args.data()+1, arg_expr_count), arg_expr_names+1))
return result;
} catch(const IScriptEnvironment::NotFound&){}
args[a+2] = arg_exprs[a]->Evaluate(env);
int HasLast = 0; // Only read if needed. 0=not loaded, 1=loaded, -1=failed

// if that fails, try with implicit "last" (except when OOP notation was used)
if (!oop_notation)
// Per-frame syntax
if (frame_number >= 0)
{
try
{
if (env2->GetVar("last", args.data()) && env2->Invoke(&result, name, AVSValue(args.data(), arg_expr_count+1), arg_expr_names))
// Try "n,args" if first arg is a clip. Only per-frame functions start with "ic".
if (arg_expr_count > 0 && args[2].IsClip()) {
args[1] = AVSValue(frame_number);
if (EvaluateSyntax(&result, name, &args, 1, env2))
return result;
} catch(const IScriptEnvironment::NotFound&){}
}

// Try "n,last,args" (except when OOP notation was used)
if (!oop_notation) {
if (HasLast == 0) // Only read if needed
HasLast = env2->GetVar("last", &args[1]) ? 1 : -1;
if (HasLast == 1) {
args[0] = AVSValue(frame_number);
if (EvaluateSyntax(&result, name, &args, 2, env2))
return result;
}
}
}

// Regular syntax
// Try "args"
if (EvaluateSyntax(&result, name, &args, 0, env2))
return result;

// Try "last,args" (except when OOP notation was used)
if (!oop_notation) {
if (HasLast == 0) // Only read if needed
HasLast = env2->GetVar("last", &args[1]) ? 1 : -1;
if (HasLast == 1) {
args[0] = AVSValue(frame_number);
if (EvaluateSyntax(&result, name, &args, 1, env2))
return result;
}
}

env->ThrowError(env->FunctionExists(name) ?
Expand All @@ -542,3 +572,13 @@ AVSValue ExpFunctionCall::Evaluate(IScriptEnvironment* env)
assert(0); // we should never get here
return 0;
}

bool ExpFunctionCall::EvaluateSyntax(AVSValue* result, const char* name, std::vector<AVSValue>* args, int extra, IScriptEnvironment2* env2) {
try
{
if (env2->Invoke(result, name, AVSValue(args->data() + 2 - extra, arg_expr_count + extra), arg_expr_names + 2 - extra))
return true;
}
catch (const IScriptEnvironment::NotFound&) {}
return false;
}
15 changes: 8 additions & 7 deletions avs_core/core/parser/expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,7 @@
#define __Expression_H__

#include <avisynth.h>

#ifdef NEW_AVSVALUE
#include <vector>
#endif

/********************************************************************
********************************************************************/
Expand Down Expand Up @@ -373,13 +370,14 @@ class ExpNot : public Expression
class ExpVariableReference : public Expression
{
public:
ExpVariableReference(const char* _name) : name(_name) {}
ExpVariableReference(const char* _name, const int _frame_number) : name(_name), frame_number(_frame_number) {}
virtual AVSValue Evaluate(IScriptEnvironment* env);

virtual const char* GetLvalue() { return name; }

private:
const char* const name;
const int frame_number; // for per-frame expressions
};


Expand Down Expand Up @@ -411,17 +409,20 @@ class ExpFunctionCall : public Expression
{
public:
ExpFunctionCall( const char* _name, PExpression* _arg_exprs,
const char** _arg_expr_names, int _arg_expr_count, bool _oop_notation );
const char** _arg_expr_names, int _arg_expr_count, bool _oop_notation, int _frame_number );
~ExpFunctionCall(void);

virtual AVSValue Evaluate(IScriptEnvironment* env);

bool EvaluateSyntax(AVSValue* result, const char* name, std::vector<AVSValue>* args, int extra, IScriptEnvironment2* env2);

private:

const char* const name;
PExpression* arg_exprs;
const char** arg_expr_names;
const int arg_expr_count;
int arg_expr_count;
const bool oop_notation;
const int frame_number;
};


Expand Down
2 changes: 1 addition & 1 deletion avs_core/core/parser/script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ AVSValue Eval(AVSValue args, void*, IScriptEnvironment* env)
{
const char *filename = args[1].AsString(0);
if (filename) filename = env->SaveString(filename);
ScriptParser parser(env, args[0].AsString(), filename);
ScriptParser parser(env, args[0].AsString(), filename, -1);
PExpression exp = parser.Parse();
return exp->Evaluate(env);
}
Expand Down
16 changes: 8 additions & 8 deletions avs_core/core/parser/scriptparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@
*******************************/


ScriptParser::ScriptParser(IScriptEnvironment* _env, const char* _code, const char* _filename)
: env(static_cast<IScriptEnvironment2*>(_env)), tokenizer(_code, _env), code(_code), filename(_filename), loopDepth(0) {}
ScriptParser::ScriptParser(IScriptEnvironment* _env, const char* _code, const char* _filename, int _frame_number)
: env(static_cast<IScriptEnvironment2*>(_env)), tokenizer(_code, _env), code(_code), filename(_filename), loopDepth(0), frame_number(_frame_number) {}

PExpression ScriptParser::Parse(void)
{
Expand Down Expand Up @@ -525,10 +525,10 @@ PExpression ScriptParser::ParseUnary(void) {
PExpression ScriptParser::ParseOOP(void)
{
#ifndef NEW_AVSVALUE
PExpression left = ParseFunction(0);
PExpression left = ParseFunction(0, frame_number);
while (tokenizer.IsOperator('.')) {
tokenizer.NextToken();
left = ParseFunction(left);
left = ParseFunction(left, frame_number);
}
#else
PExpression left = ParseFunction(0, '\0');
Expand All @@ -543,9 +543,9 @@ PExpression ScriptParser::ParseOOP(void)
}

#ifndef NEW_AVSVALUE
PExpression ScriptParser::ParseFunction(PExpression context)
PExpression ScriptParser::ParseFunction(PExpression context, int frame_number)
#else
PExpression ScriptParser::ParseFunction(PExpression context, char context_char)
PExpression ScriptParser::ParseFunction(PExpression context, int frame_number, char context_char)
#endif
{
#ifndef NEW_AVSVALUE
Expand Down Expand Up @@ -585,7 +585,7 @@ PExpression ScriptParser::ParseFunction(PExpression context, char context_char)
if (!context && !tokenizer.IsOperator('(') && !isArraySpecifier) {
#endif
// variable
return new ExpVariableReference(name);
return new ExpVariableReference(name, frame_number);
}
// function
PExpression args[max_args];
Expand Down Expand Up @@ -655,7 +655,7 @@ PExpression ScriptParser::ParseFunction(PExpression context, char context_char)
env->ThrowError("Script error: array indexing must have at least one index");
}
#endif
return new ExpFunctionCall(name, args, arg_names, i, !!context);
return new ExpFunctionCall(name, args, arg_names, i, !!context, frame_number);
}

PExpression ScriptParser::ParseAtom(void)
Expand Down
7 changes: 4 additions & 3 deletions avs_core/core/parser/scriptparser.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class ScriptParser
**/
{
public:
ScriptParser(IScriptEnvironment* _env, const char* _code, const char* _filename);
ScriptParser(IScriptEnvironment* _env, const char* _code, const char* _filename, int _frame_number);

PExpression Parse(void);

Expand All @@ -64,6 +64,7 @@ class ScriptParser
const char* const code;
const char* const filename;
int loopDepth; // how many loops are we in during parsing
int frame_number; // for per-frame expressions

void Expect(int op, const char* msg);

Expand All @@ -81,9 +82,9 @@ class ScriptParser
PExpression ParseUnary(void);
PExpression ParseOOP(void);
#ifdef NEW_AVSVALUE
PExpression ParseFunction(PExpression context, char context_char);
PExpression ParseFunction(PExpression context, int frame_number, char context_char);
#else
PExpression ParseFunction(PExpression context);
PExpression ParseFunction(PExpression context, int frame_number);
#endif
PExpression ParseAtom(void);

Expand Down
Loading