# AVSLib :: 'base' package :: 'core' module
# Copyright (c) 2005 George Zarkadas (gzarkadas@users.sourceforge.net)

# This program is free software; you can redistribute it and/or modify it under the terms of 
# the GNU General Public License as published by the Free Software Foundation; either 
# version 2 of the License, or (at your option) any later version.
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
# PURPOSE.  See the GNU General Public License for more details.
# You should have received a copy of the GNU General Public License along with this program; 
# if not, write to the "Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
# MA  02111-1307  USA"

DefineModule("avslib", "base", "core")

# Avisynth script language related constants

global MAX_INT =  2147483647
global MIN_INT = -2147483648

# Special functions corresponding to variable operations 
# Use them for constructing expressions for Eval or as building blocks of multi-argument functions.

# Private ("__") variants, intended primarily for use by AVSLib itself and extensions developers

Function __self(val x) { return x } 
Function __not(val x) { return !x } 
Function __and2(val x1, val x2) { return x1 && x2 }
Function __or2(val x1, val x2) { return x1 || x2 }
Function __xor2(val x1, val x2) { return (x1 && !x2) || (!x1 && x2) }
Function __sum2(val x1, val x2) { return x1 + x2 }
Function __dif2(val x1, val x2) { return x1 - x2 }
Function __product2(val x1, val x2) { return x1 * x2 }
Function __div2(val x1, val x2) { return x1 / x2 }
Function __mod2(val x1, val x2) { return x1 % x2 }
Function __min2(val x1, val x2) { return (x1 <= x2) ? x1 : x2 }
Function __max2(val x1, val x2) { return (x1 >= x2) ? x1 : x2 }

# Public variants, for library users; these may be rearranged to other modules, so do not add if missing

Function Self(val x) { return x } 

# Script language extensions

# Throws an error, optionally showing 'error_msg' if provided.
#
Function Throw(string "error_msg") { Assert(false, error_msg) }

# Generates an "undefined" value. Use it to set an already-defined 
# variable to an undefined state. 
#
Function Undef() { return Eval("#") }

# Returns a distinct integer value for each type. 
# 1: clip, 2:int, 3:float, 4:bool, 5:string.
# x is made optional to allow high-level functions to pass 
# undefined variables without the need to check them
#
Function VarType(val "x")
{
	return Defined(x) ? ( \
		x.IsClip ? \
			1 : ( \
		x.IsString ? \
			5 : ( \
		x.IsBool ? \
			4 : ( \
		x.IsInt ? \
			2 : ( \
		x.IsFloat ? \
			3 \
		: Throw("VarType: unsupported variable type.") )))) \
	) : 0 # 0 is reserved for undefined variables
}

# Returns a distinct string value for each type (the type's name, 
# in lowercase).
# x is made optional to allow high-level functions to pass undefined 
# variables without the need to check them
#
Function Typename(val "x")
{
	# 'undefined' in select is only a (necessary) placeholder
	return Defined(x) \
		? Select(VarType(x), "undefined", "clip", "int", "float", "bool", "string") \
		: "undefined"
}

# Returns a null (zero) value appropriate for the type of 'template' argument.
# If 'template' is not provided returns an undefined variable.
#
Function Null(val "template")
{
	vt = VarType(template)
	return vt == 0 ? \
		Undef() : ( \
	vt == 1 ? \
		BlankClip(template, length=0) \
	: \
		Select(vt - 2, 0, 0.0, false, "") )
}

# Returns true if func can be called (ie it is a function). 
# Be aware of possible side effects if func() modidies globals, since 
# it is actually called in order to find if it is callable.
# NOTE:
# When Eval(x) fails, x may under certain circumstances be Undefed (!) 
# Thus we must keep a *global* copy of it in order to achieve our purpose

Function IsCallable(string func)
{
	global __try_iscal_temp = func
	try {
		dummy = Eval(func + "()")
		flag = true		# if we are here the call was successful
	}
	catch(err_msg) {
		# if we can find the string below, then func exists 
		# but we did not supplied needed arguments
		flag = FindStr(err_msg, "arguments to function " + \
			Chr(34) + __try_iscal_temp + Chr(34)) > 0
	}
	return flag
}

Function ImportIf(bool condition, string path_true, string "path_false")
{
	return condition ? \
		Import(path_true) : ( \
	Defined(path_false) ? \
		Import(path_false) \
	: NOP )
}
