Squirrel 3.1 参考手册
首先到http://squirrel-lang.org/ 下载3.1版
压缩包解压后,里面直接有工程文件,用VS打开。
squirrel是脚本的引擎库
sqstdlib 是脚本的标准库,不是必须的,但是包含了很多基础操作
sq 编译后是一个exe,控制台程序
首先:工程默认是多字节字符集,我们全部改成Unicode字符集,因为现在的程序基本都是Unicode的了。
其次:在预处理里面添加_CRT_SECURE_NO_WARNINGS 宏,这不是必须的,可以取消警告
最后:编译Debug版本时,需要将c/c++ -> 常规 -> 调试信息格式 改为 程序数据库(/Zi),当然在 库管理器->常规->输出文件,可以将文件名后面增加一个d,用于区分Debug版和Release版
编译后就会在lib目录下生成lib文件,include 目录就是包含目录,这样我们就能使用这个库了。
——————————————————————————————————————————-
下面是官方文档的说明(翻译不一定准确,但是基本能看懂):
嵌入Squirrel
1、内存管理
Squirrel使用引用计数(RC)作为系统主要的内存管理;但是,虚拟机(VM)具有可根据需要调用的辅助标记和清除垃圾收集器。
编译时有两种可能的选项:
默认配置包括RC加上标记和清除垃圾收集器。宿主程序可以调用sq_collectgarbage()函数并在程序执行期间执行垃圾收集循环。 VM不会调用垃圾收集器,必须由宿主程序显式调用。
第二种情况仅包括RC(定义NO_GARBAGE_COLLECTOR);在这种情况下,VM无法检测参考周期,因此程序员必须明确地解决它们以避免内存泄漏。
第二个选项引入的唯一优势是在默认配置中使用垃圾收集器(32位系统为8个字节)保存2个必须为每个对象存储的附加指针。涉及的类型有:tables, arrays, functions, threads, userdata 和 generators; 其他类型都不受影响。这些选项不会影响执行速度。
2、构建配置
Unicode
通过在C ++预处理器中定义SQUNICODE 宏则采用UCS2编码,也就是Unicode
x64
通过在C ++预处理器中定义 SQ64宏,可以在64位体系结构上编译Squirrel。 该标志应该在包含’squirrel.h’的任何项目中定义。
用户数据对齐
类实例和userdata都可以有一个与之关联的缓冲区。 Squirrel通过定义SQ_ALIGNMENT的peroprocessor指定对齐(以字节为单位)。 默认情况下,SQ_ALIGNMENT被定义为4表示32位构建,8表示64位构建和构建使用64位浮点数。 可以覆盖遵循以下规则的SQ_ALIGNMENT的值。 SQ_ALIGNMENT应小于或等于SQ_MALLOC对齐,并且它应为2的幂。
注意
这仅适用于VM分配的userdata,通过sq_setclassudsize()指定或属于userdata对象。 用户指定的用户指针不受alignemnt规则的影响。
没有编译器的独立VM
通过在C ++预处理器中定义”NO_COMPILER”,可以在没有编译器的情况下编译Squirrel的VM。 当定义’NO_COMPILER’时,与编译器相关的所有函数(例如sq_compile)都将失败。 有条件地加载预编译字节码或编译文件(例如sqstd_dofile)的其他函数仅适用于预编译的字节码。
3、错误约定
API中的大多数函数返回SQRESULT值; SQRESULT指示函数是否成功完成。 宏SQ_SUCCEEDED()和SQ_FAILED()用于测试函数的结果:
if(SQ_FAILED(sq_getstring(v,-1,&s)))
printf(“getstring failed”);
4、虚拟机初始化
主机应用程序必须做的第一件事是创建一个虚拟机。 宿主应用程序可以通过sq_open()函数创建任意数量的虚拟机。 使用sq_open()创建的每个VM必须在不再需要时使用sq_close()函数释放:
int main(int argc, char* argv[])
{
HSQUIRRELVM v;
v = sq_open(1024); //creates a VM with initial stack size 1024
//do some stuff with squirrel here
sq_close(v);
}
5、栈 Stack
Squirrel通过栈与虚拟机交换值。 这种机制继承自Lua语言。 例如,要从C调用Squirrel函数,必须将函数和参数压入堆栈然后调用函数; 当Squirrel调用C函数时,参数也将在堆栈中。
栈索引:
许多API函数可以通过索引任意引用栈中的任何元素。 栈索引遵循以下约定:
1是栈底部
负索引被认为是从栈顶部的偏移量。 例如,-1是栈的顶部。
0是无效索引
下面是一个例子(让我们假设这个表是VM堆栈)
栈 | 正索引 | 父索引 |
“test” | 4 | -1(top) |
1 | 3 | -2 |
0.5 | 2 | -3 |
“foo” | 1(base) | -4 |
在这种情况下,函数sq_gettop将返回4;
栈操作:
API提供了几种从Squirrel栈中推送和检索数据的功能。
要将栈中已存在的值推到顶部位置:
void sq_push(HSQUIRRELVM v,SQInteger idx);
要弹出任意数量的元素:
void sq_pop(HSQUIRRELVM v,SQInteger nelemstopop);
要从栈中删除元素:
void sq_remove(HSQUIRRELVM v,SQInteger idx);
要检索当前虚拟栈的顶部索引(和大小),必须调用sq_gettop
SQInteger sq_gettop(HSQUIRRELVM v);
要将栈强制为特定大小,可以调用sq_settop
void sq_settop(HSQUIRRELVM v,SQInteger newtop);
如果新顶部大于前一个顶部,则栈中的新位置将填充空值。
以下函数将C值压入堆栈:
void sq_pushstring(HSQUIRRELVM v,const SQChar *s,SQInteger len);
void sq_pushfloat(HSQUIRRELVM v,SQFloat f);
void sq_pushinteger(HSQUIRRELVM v,SQInteger n);
void sq_pushuserpointer(HSQUIRRELVM v,SQUserPointer p);
void sq_pushbool(HSQUIRRELVM v,SQBool b);
此函数将null压入栈:
void sq_pushnull(HSQUIRRELVM v);
返回栈中任意位置的值的类型:
SQObjectType sq_gettype(HSQUIRRELVM v,SQInteger idx);
结果可以是以下值之一:
OT_NULL,OT_INTEGER,OT_FLOAT,OT_STRING,OT_TABLE,OT_ARRAY,OT_USERDATA,
OT_CLOSURE,OT_NATIVECLOSURE,OT_GENERATOR,OT_USERPOINTER,OT_BOOL,OT_INSTANCE,OT_CLASS,
OT_WEAKREF
以下函数将栈中的squirrel值转换为C值:
SQRESULT sq_getstring(HSQUIRRELVM v,SQInteger idx,const SQChar **c);
SQRESULT sq_getinteger(HSQUIRRELVM v,SQInteger idx,SQInteger *i);
SQRESULT sq_getfloat(HSQUIRRELVM v,SQInteger idx,SQFloat *f);
SQRESULT sq_getuserpointer(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p);
SQRESULT sq_getuserdata(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p,SQUserPointer *typetag);
SQRESULT sq_getbool(HSQUIRRELVM v,SQInteger idx,SQBool *p);
函数sq_cmp比较栈中的2个值并返回它们的关系(如ANSI C中的strcmp()):
SQInteger sq_cmp(HSQUIRRELVM v);
6、运行时错误处理
当使用带有try / catch语句的Squirrel代码处理异常时,会引发运行时错误并中断当前程序的执行。 可以设置回调函数来拦截来自主程序的运行时错误; 这对于向脚本编写器显示有意义的错误以及实现可视化调试器很有用。 以下API调用从栈中弹出Squirrel函数并将其设置为错误处理程序:
SQUIRREL_API void sq_seterrorhandler(HSQUIRRELVM v);
使用2个参数,环境对象(this)和对象调用错误处理程序。 对象可以是任何Squirrel类型。
7、编译脚本
您可以使用sq_compile函数编译Squirrel脚本:
typedef SQInteger (*SQLEXREADFUNC)(SQUserPointer userdata);
SQRESULT sq_compile(HSQUIRRELVM v,SQREADFUNC read,SQUserPointer p,
const SQChar *sourcename,SQBool raiseerror);
为了编译脚本,主机应用程序必须实现一个读取器函数(SQLEXREADFUNC); 此函数用于向编译器提供脚本数据。 每次编译器需要一个字符时都会调用该函数; 如果成功则必须返回字符代码,如果源码完成则返回0。
如果sq_compile成功,则编译后的脚本将作为Squirrel函数压入到栈中。
这是一个从文件中读取的”read”函数的示例:
SQInteger file_lexfeedASCII(SQUserPointer file)
{
int ret;
char c;
if( ( ret=fread(&c,sizeof(c),1,(FILE *)file )>0) )
return c;
return 0;
}
int compile_file(HSQUIRRELVM v,const char *filename)
{
FILE *f=fopen(filename,”rb”);
if(f)
{
sq_compile(v,file_lexfeedASCII,f,filename,1);
fclose(f);
return 1;
}
return 0;
}
当编译器因语法错误而失败时,它将尝试调用”编译器错误处理程序”; 此函数必须声明如下:
typedef void (*SQCOMPILERERROR)(HSQUIRRELVM /*v*/,const SQChar * /*desc*/,const SQChar * /*source*/, SQInteger /*line*/,SQInteger /*column*/);
并且可以使用以下API调用进行设置:
void sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f);
8、调用函数
要调用squirrel函数,必须在栈中压入函数跟参数后,然后调用函数sq_call。 如果最后一个sq_call参数> 0,该函数将弹出参数并压入返回值。
sq_pushroottable(v);
sq_pushstring(v,”foo”,-1);
sq_get(v,-2); //从根表获取函数
sq_pushroottable(v); //’this’ (函数环境对象)
sq_pushinteger(v,1);
sq_pushfloat(v,2.0);
sq_pushstring(v,”three”,-1);
sq_call(v,4,SQFalse);
sq_pop(v,2); //弹出根表和函数
这相当于以下Squirrel代码:
foo(1,2.0,”three”);
如果在执行squirrel代码期间发生运行时错误(或抛出异常),则sq_call将失败。
9、创建C函数
本机C函数必须具有以下原型:
typedef SQInteger (*SQFUNCTION)(HSQUIRRELVM);
参数是调用VM的句柄,返回值是一个遵循以下规则的整数:
如果函数返回值,则返回1
如果函数未返回值,则为0
抛出SQ_ERROR运行时错误
为了从C函数指针获取新的可调用squirrel函数,需要调用sq_newclosure()将C函数传递给它;新的Squirrel函数将被压入栈。
调用该函数时,stackbase是函数的第一个参数,top是最后一个参数。为了返回一个值,函数必须将其压入栈并返回1。
函数参数位于从位置1(’this’)到n的栈中。 sq_gettop()可用于确定参数的数量。
如果函数具有自由变量,那么在显式参数之后,这些变量可以作为普通参数处理。另请注意,sq_gettop()返回的值将受自由变量的影响。 sq_gettop()将返回参数数量加上自由变量数量。
这里有一个例子,下面的函数打印每个参数的值并返回参数个数。
SQInteger print_args(HSQUIRRELVM v)
{
SQInteger nargs = sq_gettop(v); //number of arguments
for(SQInteger n=1;n<=nargs;n++)
{
printf(“arg %d is “,n);
switch(sq_gettype(v,n))
{
case OT_NULL:
printf(“null”);
break;
case OT_INTEGER:
printf(“integer”);
break;
case OT_FLOAT:
printf(“float”);
break;
case OT_STRING:
printf(“string”);
break;
case OT_TABLE:
printf(“table”);
break;
case OT_ARRAY:
printf(“array”);
break;
case OT_USERDATA:
printf(“userdata”);
break;
case OT_CLOSURE:
printf(“closure(function)”);
break;
case OT_NATIVECLOSURE:
printf(“native closure(C function)”);
break;
case OT_GENERATOR:
printf(“generator”);
break;
case OT_USERPOINTER:
printf(“userpointer”);
break;
case OT_CLASS:
printf(“class”);
break;
case OT_INSTANCE:
printf(“instance”);
break;
case OT_WEAKREF:
printf(“weak reference”);
break;
default:
return sq_throwerror(v,”invalid param”); //throws an exception
}
}
printf(“\n”);
sq_pushinteger(v,nargs); //push the number of arguments as return value
return 1; //1 because 1 value is returned
}
这里有一个如何注册函数的例子:
SQInteger register_global_func(HSQUIRRELVM v,SQFUNCTION f,const char *fname)
{
sq_pushroottable(v);
sq_pushstring(v,fname,-1);
sq_newclosure(v,f,0,0); //create a new function
sq_newslot(v,-3,SQFalse);
sq_pop(v,1); //pops the root table
}
10、表和数组操作
创建一个新表调用sq_newtable,该函数在栈中压入一个新表:
void sq_newtable(HSQUIRRELVM v);
要创建新插槽:
SQRESULT sq_newslot(HSQUIRRELVM v,SQInteger idx,SQBool bstatic);
设置或获取表委托:
SQRESULT sq_setdelegate(HSQUIRRELVM v,SQInteger idx);
SQRESULT sq_getdelegate(HSQUIRRELVM v,SQInteger idx);
创建一个新数组调用sq_newarray,该函数在栈中压入一个新数组; 如果参数size大于0,则元素初始化为null:
void sq_newarray (HSQUIRRELVM v,SQInteger size);
要将值附加到数组的后面:
SQRESULT sq_arrayappend(HSQUIRRELVM v,SQInteger idx);
要从数组后面删除值:
SQRESULT sq_arraypop(HSQUIRRELVM v,SQInteger idx,SQInteger pushval);
要调整数组大小:
SQRESULT sq_arrayresize(HSQUIRRELVM v,SQInteger idx,SQInteger newsize);
要获取表或数组的大小,必须使用sq_getsize():
SQInteger sq_getsize(HSQUIRRELVM v,SQInteger idx);
要在数组或表中设置值:
SQRESULT sq_set(HSQUIRRELVM v,SQInteger idx);
要从数组或表中获取值:
SQRESULT sq_get(HSQUIRRELVM v,SQInteger idx);
从没有使用委托的表中获取或设置值:
SQRESULT sq_rawget(HSQUIRRELVM v,SQInteger idx);
SQRESULT sq_rawset(HSQUIRRELVM v,SQInteger idx);
迭代表或数组:
SQRESULT sq_next(HSQUIRRELVM v,SQInteger idx);
这是一个如何执行迭代的示例:
//在这里压入你的 table/array
sq_pushnull(v) // null iterator
while(SQ_SUCCEEDED(sq_next(v,-2)))
{
//这里-1是值,-2是键
sq_pop(v,2); //在下一次迭代之前弹出键和值
}
sq_pop(v,1); //pops the null iterator
11、用户数据和用户指针(Userdata和UserPointers)
Squirrel允许宿主应用程序将任意数据块放入Squirrel值,这可以通过数据类型userdata:
SQUserPointer sq_newuserdata(HSQUIRRELVM v,SQUnsignedInteger size);
当调用sq_newuserdata函数时,Squirrel会分配一个具有指定大小的新用户数据,返回指向其有效缓冲区的指针并将该对象压入堆栈中; 此时应用程序可以使用此内存块执行任何操作,VM将自动执行内存释放的操作,就像其他所有内置类型一样。 用户数据可以传递给函数或存储在表槽中。 默认情况下,Squirrel无法直接操纵userdata; 但是可以为其分配一个委托并定义一个类似于表的行为。应用程序可能希望对存储在userdata对象在删除时,对数据执行某些操作,因此可以在删除某个用户数据之前分配将由VM调用的回调。 这是通过API调用sq_setreleasehook完成的:
typedef SQInteger (*SQRELEASEHOOK)(SQUserPointer,SQInteger size);
void sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook);
另一种用户数据是用户指针; 这种类型不像普通用户数据那样是一个内存块,而只是一个’void *’指针。 它不能有委托并且按值传递,因此推送用户指针不会导致任何内存分配:
void sq_pushuserpointer(HSQUIRRELVM v,SQUserPointer p);
12、注册表( registry table )
注册表是vm和他所有线程(朋友vms)之间共享的隐藏表。 此表只能通过C API访问,并且是本机C库实现的实用程序结构。 例如,sqstdlib(squirrel标准库)使用它来存储配置和共享对象委托。 可以通过API调用sq_pushregistrytable()访问注册表:
void sq_pushregistrytable(HSQUIRRELVM v);
13、维护对C API中Squirrel值的引用
Squirrel允许通过C API引用值; 函数sq_getstackobj()获取一个squirrel对象(任何类型)的句柄。 对象句柄可用于通过添加或删除对象的引用来控制对象的生命周期(请参阅sq_addref()和sq_release())。 也可以使用sq_pushobject()将对象重新推送到VM堆栈中:
HSQOBJECT obj;
sq_resetobject(v,&obj) // 初始化对象句柄
sq_getstackobj(v,-2,&obj); //从pos -2中获取一个对象句柄
sq_addref(v,&obj); //对象添加引用
… //do stuff
sq_pushobject(v,&obj); //将对象压入栈
sq_release(v,&obj); //释放对象
14、调试接口
squirrel VM提供了一个非常简单的调试接口,可以轻松构建一个功能齐全的调试器。 通过函数sq_setdebughook和sq_setnativedebughook实际上可以设置一个回调函数,该函数将在每次VM执行脚本的新行或函数被调用/返回时调用。 回调将作为参数传递当前行当前源和当前函数名称(如果有):
SQUIRREL_API void sq_setdebughook(HSQUIRRELVM v);
或
SQUIRREL_API void sq_setnativedebughook(HSQUIRRELVM v,SQDEBUGHOOK hook);
以下代码显示了调试钩子(显然也可以在C中实现此功能)。
function debughook(event_type,sourcefile,line,funcname)
{
local fname=funcname?funcname:”unknown”;
local srcfile=sourcefile?sourcefile:”unknown”
switch (event_type) {
case ‘l’: //called every line(that contains some code)
::print(“LINE line [” + line + “] func [” + fname + “]”);
::print(“file [” + srcfile + “]\n”);
break;
case ‘c’: //called when a function has been called
::print(“LINE line [” + line + “] func [” + fname + “]”);
::print(“file [” + srcfile + “]\n”);
break;
case ‘r’: //called when a function returns
::print(“LINE line [” + line + “] func [” + fname + “]”);
::print(“file [” + srcfile + “]\n”);
break;
}
}
参数event_type可以是’l’,’c’或’r’; 对于执行的每行调用带有’l’事件的钩子,每次调用函数时调用’c’,每次函数返回时调用’r’。
功能齐全的调试器始终允许显示局部变量和调用堆栈。 通过sq_getstackinfos()检索调用堆栈信息:
SQInteger sq_stackinfos(HSQUIRRELVM v,SQInteger level,SQStackInfos *si);
而局部变量info通过sq_getlocal():
SQInteger sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger nseq);
为了接收行回调,必须在启用调试信息的情况下编译脚本,这通过sq_enabledebuginfo();
void sq_enabledebuginfo(HSQUIRRELVM v, SQInteger debuginfo);
Squirrel语法
1、词汇结构
(1)标识符
标识符以字母字符或”_”开头,后跟任意数量的字母字符,”_”或数字([0-9])。 Squirrel是一种区分大小写的语言,这意味着同一个字母字符的小写和大写表示被视为不同的字符。 例如,”foo”,”Foo”和”fOo”将被视为3个不同的标识符。
(2)关键字
以下单词是语言的保留字,不能用作标识符:
base | break | case | catch | class | clone |
continue | const | default | delete | else | enum |
extends | for | foreach | function | if | in |
local | null | resume | return | switch | this |
throw | try | typeof | while | yield | constructor |
instanceof | true | false | static | __LINE__ | __FILE__ |
(3)操作符
! | != | || | == | && | >= | <= | > |
<=> | + | += | – | -= | / | /= | * |
*= | % | %= | ++ | — | <- | = | & |
^ | | | ~ | >> | << | >>> |
(4)其他符号
{ | } | [ | ] | . | : |
:: | ‘ | ; | “ | @” |
(5)字面常量
34 | Integer number(base 10) |
0xFF00A120 | Integer number(base 16) |
0753 | Integer number(base 8) |
‘a’ | Integer number |
1.52 | Floating point number |
1.e2 | Floating point number |
1.e-2 | Floating point number |
“I’m a string” | String |
@”I’m a verbatim string” | String |
@” I’m a multiline verbatim string “ | String |
(6)注释
// 单行注释
/* */ 多行注释
# 单行注释
2、值和数据类型
(1)Interger
整数表示32位的带符号数:
local a = 123 //decimal
local b = 0x0012 //hexadecimal
local c = 075 //octal
local d = ‘w’ //char code
(2)Float
float表示32位的浮点数:
local a=1.0
local b=0.234
(3)String
字符串是一个不可变的字符序列,修改字符串是创建一个新字符串。
Squirrel的字符串,表现得像C或C ++,用引号(”)分隔,可以包含转义序列(\ t,\ a,\ b,\ n,\ r,\ v,\ f,\\,\”, \’,\ 0,\ x <hh>,\ u <hhhh>和\ U <hhhhhhhh>)。
照字面的字符串文字以@”开头并以匹配的引号结尾。照字面的字符串文字也可以延伸到换行符。如果它们这样做,它们包括引号之间的任何空格字符:
local a = “I’m a wonderful string\n”
// 在字符串的末尾有一个换行符
local x = @”I’m a verbatim string\n”
// \ n被复制到与常规字符串中的\\ n相同的字符串中”I’m a verbatim string\n”
对于逐字字符串文字的”无转义序列”规则的唯一例外是,您可以通过两个双引号来转义双引号:
local multiline = @”
this is a multiline string
it will “”embed”” all the new line
characters
“
(4)Null
null值是一个原始值,表示null,empty或不存在的引用。 Null类型只有一个值,称为null:
local a = null
(5)Bool
bool数据类型只能有两个。 他们是true和false的文字。 bool值表示条件的有效性(告知条件是真还是假):
(6)Table
是关联容器,实现为键/值对(称为插槽):
local t={}
local test=
{
a=10
b=function(a) { return a+1; }
}
(7)Array
数组是简单的对象序列,它们的大小是动态的,它们的索引始终从0开始:
local a = [“I’m”,”an”,”array”]
local b = [null]
b[0] = a[2];
(8)Function
函数类似于其他类C语言和大多数编程语言的函数,但是有一些关键的区别(见下文)。
(9)Class
类是作为键/值对实现的关联容器。 类是通过”类表达式”或”类语句”创建的。 类成员可以在创建时从另一个类对象继承。 创建成员后,可以添加成员,直到类的实例创建。
(10)Class Instance
通过调用类对象来创建类实例。 作为表的实例是作为键/值对实现的。 无法同步添加或删除实例成员,但可以更改成员的值。
(11)Generator
生成器是可以使用语句”yield”暂停并稍后恢复的函数(请参阅生成器)。
(12)Userdata
Userdata对象是由宿主应用程序定义但存储在Squirrel变量中的内存块(或指针)(请参阅Userdata和UserPointers)。
(13)Thread
线程是表示协作执行线程的对象,也称为协同程序。
(14) Weak References
弱引用是指向另一个(非标量)对象的对象,但不具有对它的强引用。 (参见弱引用)。
3、执行上下文
执行上下文是函数栈帧和函数环境对象(this)以及函数root(根表)的并集。栈帧是栈的一部分,其中存储了在其正文中声明的局部变量。环境对象是一个隐式参数,由函数调用者自动传递。根表是在创建期间与该函数关联的表。函数的根表值是函数创建时VM的根表。使用closure.setroot()创建后,也可以更改函数的根表。在执行期间,函数体只能透明地引用其执行上下文。这意味着单个标识符可以引用局部变量,环境对象槽或闭包根表的槽;可以通过关键字this显式访问环境对象。可以通过operator ::显式访问闭包根表。
(1) 变量
Squirrel中有两种类型的变量,局部变量和表/数组槽。 因为全局变量(存储在闭包根中的变量)存储在表中,所以它们是表槽。
单个标识符是指环境对象中的局部变量或槽:
derefexp := id;
_table[“foo”]
_array[10]
使用表我们也可以使用’.’语法:
derefexp := exp ‘.’ id
_table.foo
Squirrel首先检查标识符是否是局部变量(函数参数是局部变量),如果没有查找环境对象(this)并最终查找到闭包根。
例如:
function testy(arg)
{
local a=10;
print(a);
return arg;
}
在这种情况下,’foo’将等同于’this.foo’或此[“foo”]。
全局变量存储在称为根表的表中。 通常在全局范围内,环境对象是根表,但是要从另一个范围显式访问函数的闭包根,插槽名称必须以”::”(:: foo)为前缀。
例如:
function testy(arg)
{
local a=10;
return arg+::foo;
}
访问闭包根表中的变量’foo’。
由于Squirrel 3.1每个函数都有一个对特定根表的弱引用,这可能与当前的VM根表不同:
function test() {
foo = 10;
}
相当于写:
function test() {
if(“foo” in this) {
this.foo = 10;
}else {
::foo = 10;
}
}
4、声明
Squirrel程序是一个简单的语句序列:
stats := stat [‘;’|’\n’] stats
Squirrel语句与C系列语言(C / C ++,Java,C#等……)相当:赋值,函数调用,程序流控制结构等。加上一些自定义语句,如yield,table和array constructors(这些将在本文档后面详细介绍。 语句可以用新行或’;’(或使用关键字case或default,如果在switch / case语句中)分隔,如果语句后跟’}’,则不需要这两个符号。
(1)语句块
stat := ‘{‘ stats ‘}’
由大括号({})分隔的一系列语句称为块; 块是一个声明本身。
(2) 控制流程语句
squirrel实现了最常见的控制流语句:
if, while, do-while, switch-case, for, foreach
(2.1)true and false
Squirrel有一个布尔类型(bool),但是像C ++一样,它认为null,0(整数)和0.0(浮点)为false,任何其他值都被认为是真的。
(2.2) if/else
stat:= ‘if’ ‘(‘ exp ‘)’ stat [‘else’ stat]
根据表达式的结果有条件地执行语句:
if(a>b)
a=b;
else
b=a;
////
if(a==10)
{
b=a+b;
return a;
}
(2.3) while
stat:= ‘while’ ‘(‘ exp ‘)’ stat
条件为真时执行语句:
function testy(n)
{
local a=0;
while(a<n) a+=1;
while(1)
{
if(a<0) break;
a-=1;
}
}
(2.4)do/while
stat:= ‘do’ stat ‘while’ ‘(‘ expression ‘)’
执行一次语句,然后重复执行语句,直到条件表达式求值为false:
local a=0;
do
{
print(a+”\n”);
a+=1;
} while(a>100)
(2.5) switch
stat := ‘switch’ ”( exp ‘)’ ‘{‘
‘case’ case_exp ‘:’
stats
[‘default’ ‘:’
stats]
‘}’
Switch是一个控制语句,允许通过将控制权传递给其正文中的一个case语句来多次选择代码。 如果case都不匹配会跳转到default标签(如果存在),如果是case实例,则控制将转移到case_exp与exp匹配的case标签。switch语句可以包含多个case,如果2个case具有相同的表达式结果,则将首先考虑第一个。default标签只允许一次,必须是最后一个。 break语句将跳转到switch块之外。
(3) 循环
(3.1) for
stat:= ‘for’ ‘(‘ [initexp] ‘;’ [condexp] ‘;’ [incexp] ‘)’ statement
只要条件不等于false,就执行一个语句:
for(local a=0;a<10;a+=1)
print(a+”\n”);
//or
glob <- null
for(glob=0;glob<10;glob+=1){
print(glob+”\n”);
}
//or
for(;;){
print(loops forever+”\n”);
}
(3.2) foreach
‘foreach’ ‘(‘ [index_id’,’] value_id ‘in’ exp ‘)’ stat
对包含在array, table, class, string or generator中的每个元素执行语句。 如果exp是一个生成器,它将在每次迭代时恢复,只要它是活着的; 该值将是’resume’的结果,索引是从0开始的迭代序列号:
local a=[10,23,33,41,589,56]
foreach(idx,val in a)
print(“index=”+idx+” value=”+val+”\n”);
//or
foreach(val in a)
print(“value=”+val+”\n”);
(4) break
stat := ‘break’
break语句终止循环的执行(for,foreach,while或do / while)或跳出switch语句;
(5) continue
stat := ‘continue’
continue运算符跳转到循环的下一次迭代,跳过以下语句的执行。
(6) return
stat:= return [exp]
return语句终止当前函数/生成器的执行,并可选择返回表达式的结果。 如果省略表达式,则函数将返回null。 如果在发生器内使用return语句,则生成器将不再可恢复。
(7) yield
stat := yield [exp]
(见生成器)
(8) 局部变量声明
initz := id [= exp][‘,’ initz]
stat := ‘local’ initz
可以在程序中的任何位置声明局部变量; 它们存在于它们的声明到它们已被声明的块的末尾之间。 EXCEPTION:允许局部变量声明语句作为for循环中的第一个表达式:
for(local a=0;a<10;a+=1)
print(a);
(9) 函数声明
funcname := id [‘::’ id]
stat:= ‘function’ id [‘::’ id]+ ‘(‘ args ‘)’ stat
创建一个新函数
(10) 类声明
memberdecl := id ‘=’ exp [‘;’] | ‘[‘ exp ‘]’ ‘=’ exp [‘;’] | functionstat | ‘constructor’ functionexp
stat:= ‘class’ derefexp [‘extends’ derefexp] ‘{‘
[memberdecl]
‘}’
创建一个新类
(11) try/cach
stat:= ‘try’ stat ‘catch’ ‘(‘ id ‘)’ stat
try语句包含一个代码块,其中可能发生异常情况,例如运行时错误或throw语句。 catch子句提供异常处理代码。 当catch子句捕获异常时,其id绑定到该异常。
(12) throw
stat:= ‘throw’ exp
抛出异常。 可以抛出任何值。
(13) const
stat:= ‘const’ id ‘=’ ‘Integer | Float | StringLiteral
声明一个常量(请参阅常量和枚举)。
(12) enum
enumerations := ( ‘id’ ‘=’ Integer | Float | StringLiteral ) [‘,’]
stat:= ‘enum’ id ‘{‘ enumerations ‘}’
(13) 表达式
stat := exp
在Squirrel中,每个表达式也被允许作为语句,如果是这样,表达式的结果将被丢弃。
5、表达式
(1) 赋值
exp := derefexp ‘=’ exp
exp:= derefexp ‘<-‘ exp
squirrel实现了2种赋值:正常赋值(=):
a = 10;
和”新槽”赋值:
a <- 10;
新槽表达式允许在表中添加一个新槽。如果表中已存在插槽,则其行为类似于正常赋值。
(2) 操作符
(2.1) ?: 操作符
exp := exp_cond ‘?’ exp1 ‘:’ exp2
根据表达式的结果有条件地评估表达式。
(2.2) 算术操作符
exp:= ‘exp’ op ‘exp’
Squirrel支持标准算术运算符+, – ,*,/和%。 除此之外还支持联合运算符(+ =, – =,* =,/ =,%=)和递增和递减运算符(++和 – );:
a += 2;
//is the same as writing
a = a + 2;
x++
//is the same as writing
x = x + 1
所有操作符都可以正常使用整数和浮点数; 如果一个操作数是一个整数而一个是浮点数,则表达式的结果将是float。 +运算符具有字符串的特殊行为; 如果其中一个操作数是一个字符串,则operator +将尝试将另一个操作数转换为字符串并将它们连接在一起。 对于实例和表,调用_tostring。
(2.3) 关系操作符
exp:= ‘exp’ op ‘exp’
Squirrel中的关系运算符是:==, <, <=, <, <=, !=
(2.4) 三比较
exp:= ‘exp’ <=> ‘exp’
三比较运算符<=>比较2个值A和B,如果A <B则返回小于0的整数,如果A == B则返回0,如果A> B则返回大于0的整数。
(2.5) 逻辑运算符
exp := exp op exp
exp := ‘!’ exp
Squirrel中的逻辑运算符是:&&,|| ,!
如果第一个参数为null,则运算符&&(逻辑与)返回null,否则返回其第二个参数。 操作符|| (逻辑或)如果不是null则返回其第一个参数,否则返回第二个参数。
如果给定的否定值不是null,则’!’运算符将返回null,如果给定的值为null,则返回不为null的值。
(2.6) in 操作符
exp:= keyexp ‘in’ tableexp
测试表中是否存在插槽。 如果keyexp是tableexp中的有效键,则返回true
local t=
{
foo=”I’m foo”,
[123]=”I’m not foo”
}
if(“foo” in t) dostuff(“yep”);
if(123 in t) dostuff();
(2.7) instanceof 操作符
exp:= instanceexp ‘instanceof’ classexp
测试类实例是否是某个类的实例。 如果instanceexp是classexp的实例,则返回true。
(2.8) typeof 操作符
exp:= ‘typeof’ exp
以字符串形式返回值的类型名称:
local a={},b=”squirrel”
print(typeof a); //will print “table”
print(typeof b); //will print “string”
(2.9) 逗号操作符
exp:= exp ‘,’ exp
逗号运算符从左到右计算两个表达式,运算符的结果是右边表达式的结果; 左表达式的结果被丢弃:
local j=0,k=0;
for(local i=0; i<10; i++ , j++)
{
k = i + j;
}
local a,k;
a = (k=1,k+2); //a becomes 3
(2.10) 位操作符
exp:= ‘exp’ op ‘exp’
exp := ‘~’ exp
Squirrel支持标准的c-like bit wise运算符&,|,^,〜,<<,>>加上无符号右移运算符<<<。 除了将左操作数视为无符号整数外,无符号右移与普通右移运算符(<<)完全相同,因此不受符号的影响。 这些运算符仅处理整数值,将任何其他操作数类型传递给这些运算符将导致异常。
(2.11) 运算符优先级
-, ~, !, typeof , ++, — | 最高 |
/, *, % | … |
+, – | |
<<, >>, >>> | |
<, <=, >, >= | |
==, !=, <=> | |
& | |
^ | |
&&, in | |
+=, =, -= | … |
,(comma operator) | 最低 |
(3) Table 构造函数
tslots := ( ‘id’ ‘=’ exp | ‘[‘ exp ‘]’ ‘=’ exp ) [‘,’]
exp := ‘{‘ [tslots] ‘}’
创建一个新表:
local a = {} //create an empty table
表构造函数也可以包含槽声明; 使用语法:
local a = {
slot1 = “I’m the slot value”
}
替代语法可以是:
‘[‘ exp1 ‘]’ = exp2 [‘,’]
创建一个新的插槽,其中exp1为键,exp2为值:
local a=
{
[1]=”I’m the value”
}
两种语法都可以混合使用:
local table=
{
a=10,
b=”string”,
[10]={},
function bau(a,b)
{
return a+b;
}
}
插槽之间的逗号是可选的。
(3.1) Table 的json语法
因为Squirrel 3.0可以使用JSON语法声明一个表
以下JSON代码段:
local x = {
“id”: 1,
“name”: “Foo”,
“price”: 123,
“tags”: [“Bar”,”Eek”]
}
相当于以下Squirrel代码:
local x = {
id = 1,
name = “Foo”,
price = 123,
tags = [“Bar”,”Eek”]
}
(4) Clone
exp:= ‘clone’ exp
克隆表,数组或类实例执行浅拷贝(复制新对象中的所有插槽而不进行递归)。 如果源表具有委托,则同一委托将被指定为新表的委托(未复制)(请参阅委托)。
在新对象准备好之后,调用”_cloned”元方法(参见Metamethods)。
克隆类实例时,不会调用构造函数(初始化必须依赖于`_cloned`)
(5) 数组构造
exp := ‘[‘ [explist] ‘]’
创建一个新数组
a <- [] //creates an empty array
在构造期间可以使用值初始化数组:
a <- [1,”string!”,[],{}] //creates an array with 4 elements
6、Tables 表
表是关联容器,实现为键/值对(称为槽); 值可以是任何可能的类型,键是除”null”之外的任何类型。 Table是squirrel的骨架,委托和许多其他功能都是通过这种类型实现的; 甚至存储”全局”变量的环境也是一个表(称为根表)。
(1) 构造函数
表是通过表构造函数创建的(请参阅表构造函数)
(2) 槽创建
在现有表中添加新插槽是通过”新插槽”操作符< – ; 此运算符的行为类似于正常赋值,但如果插槽不存在则将创建:
local a = {}
以下行将导致异常,因为表’a’中不存在名为’newslot’的插槽:
a.newslot = 1234
这将成功:
a.newslot <- 1234;
或
a[1] <- “I’m the value of the new slot”;
(3)槽删除
exp:= delete derefexp
删除插槽是通过关键字delete完成的; 此表达式的结果将是删除的插槽的值:
a <- {
test1=1234
deleteme=”now”
}
delete a.test1
print(delete a.deleteme); //this will print the string “now”
7、Arrays 数组
数组是一个由0到数组大小减去1的整数索引的值序列。数组元素可以通过它们的索引获得:
local a=[“I’m a string”, 123]
print(typeof a[0]) //prints “string”
print(typeof a[1]) //prints “integer”
调整数组和数组元素的大小,插入,删除是通过一组标准函数完成的(参见内置函数)。
8、Functions 函数
函数是类的第一个值,像整数或字符串且可以存储在表槽,局部变量、数组、且可作为函数参数传递。 函数可以用Squirrel或本机语言实现,调用约定与ANSI C兼容。
(8.1) 函数声明
函数通过函数表达式声明:
local a = function(a, b, c) { return a + b – c; }
或者用语法糖:
function ciao(a,b,c)
{
return a+b-c;
}
这相当于:
this.ciao <- function(a,b,c)
{
return a+b-c;
}
可以使用此语法糖声明局部函数:
local function tuna(a,b,c)
{
return a+b-c;
}
这相当于:
local tuna = function(a,b,c)
{
return a+b-c;
}
也可以声明类似的:
T <- {}
function T::ciao(a,b,c)
{
return a+b-c;
}
//that is equivalent to write
T.ciao <- function(a,b,c)
{
return a+b-c;
}
//or
T <- {
function ciao(a,b,c)
{
return a+b-c;
}
}
(8.1.1) 默认参数
Squirrel的函数可以有默认参数。
具有默认参数的函数声明如下:
function test(a,b,c = 10, d = 20)
{
….
}
当调用函数test并且未指定参数c或d时,VM会自动将默认值分配给未指定的参数。 默认参数可以是任何有效的squirrel表达式。 表达式在运行时进行检查。
(8.1.2) 具有可变参数数量的函数
Squirrel的函数可以有不同数量的参数(varargs函数)。
通过在参数列表的末尾添加三个点(…)来声明vararg函数。
调用该函数时,所有额外参数都可以通过名为vargv的数组访问,该数组作为隐式参数传递。
vargv是一个常规的squirrel数组,可以相应地使用:
function test(a,b,…)
{
for(local i = 0; i< vargv.len(); i++)
{
::print(“varparam “+i+” = “+vargv[i]+”\n”);
}
foreach(i,val in vargv)
{
::print(“varparam “+i+” = “+val+”\n”);
}
}
test(“goes in a”,”goes in b”,0,1,2,3,4,5,6,7,8);
(8.2) 函数调用
exp:= derefexp ‘(‘ explist ‘)’
表达式按以下顺序计算:expre(arguments)之后的derefexp和调用结束时的derefexp。
Squirrel中的每个函数调用都将环境对象作为隐藏参数传递给被调用函数。 ‘this’参数是函数索引的对象。
如果我们使用以下语法调用函数:
table.foo(a)
传递给foo的环境对象将是’table’:
foo(x,y) // equivalent to this.foo(x,y)
环境对象将是this(与调用函数相同)。
(8.3) 将环境绑定到函数
而默认情况下,squirrel函数调用作为环境对象’this’传递,该对象是函数索引的对象。 但是,也可以使用内置方法closure.bindenv(env_obj)将环境静态绑定到闭包。 方法bindenv()返回一个绑定环境的新实例。 当环境对象绑定到函数时,每次调用该函数时,其”this”参数将始终是先前绑定的环境。 此机制对于实现类似于C#委托的回调系统很有用。
注意:闭包保持对绑定环境对象的弱引用,因为如果删除该对象,则对闭包的下一次调用将导致null环境对象。
(8.4) Lambda 表达式
exp := ‘@’ ‘(‘ paramlist ‘)’ exp
Lambda表达式是一种快速定义由单个表达式组成的函数的同义语法糖。 应用函数式编程模式时,此功能非常方便,例如map / reduce或将compare方法传递给array.sort()。
这里有一个lambda表达式:
local myexp = @(a,b) a + b
这相当于:
local myexp = function(a,b) { return a + b; }
一个更有用的用法可能是:
local arr = [2,3,5,8,3,5,1,2,6];
arr.sort(@(a,b) a <=> b);
arr.sort(@(a,b) -(a <=> b));
本可以写成:
local arr = [2,3,5,8,3,5,1,2,6];
arr.sort(function(a,b) { return a <=> b; } );
arr.sort(function(a,b) { return -(a <=> b); } );
除了限于单个表达式,lambdas支持常规函数的所有功能。 实际上是作为编译时功能实现的。
(8.5) 自由变量
自由变量是函数作用域外部的变量,因为它不是函数的局部变量或参数。 自由变量引用外部范围的局部变量。 在下面的例子中,变量’testy’,’x’和’y’绑定到函数’foo’:
local x=10,y=20
local testy=”I’m testy”
function foo(a,b)
{
::print(testy);
return a+b+x+y;
}
程序可以读取或写入自由变量。
(8.6) 尾递归
尾递归是一种将程序中的递归部分转换为迭代的方法:当函数中的递归调用是该函数中最后执行的语句(就在返回之前)时。 如果发生这种情况,松鼠解释器会在递归调用之前折叠调用者堆栈帧; 因为非常深的递归是可能的,没有堆栈溢出的风险:
function loopy(n)
{
if(n>0){
::print(“n=”+n+”\n”);
return loopy(n-1);
}
}
loopy(1000);
9、Classes 类
Squirrel实现了类似于Java / C ++ /等语言的类机制……但是由于它的动态特性,它在几个方面有所不同。 Classes 是第一类对象,像整数或字符串一样,可以存储在表槽、局部变量,数组,且可作为函数参数传递。
(9.1) 类的声明
通过关键字”class”创建一个类对象。 类对象遵循表的相同声明语法(参见表),唯一的区别是使用’;’作为可选的分隔符而不是’,’。
例如:
class Foo {
//构造函数
constructor(a)
{
testy = [“stuff”,1,2,3,a];
}
//成员方法
function PrintTesty()
{
foreach(i,val in testy)
{
::print(“idx = “+i+” = “+val+” \n”);
}
}
//属性
testy = null;
}
以上的代码示例是一个语法糖自:
Foo <- class {
//构造函数
constructor(a)
{
testy = [“stuff”,1,2,3,a];
}
//成员方法
function PrintTesty()
{
foreach(i,val in testy)
{
::print(“idx = “+i+” = “+val+” \n”);
}
}
//属性
testy = null;
}
为了模拟名称空间,也可以声明这样的:
//只有2个常规嵌套表
FakeNamespace <- {
Utils = {}
}
class FakeNamespace.Utils.SuperClass {
constructor()
{
::print(“FakeNamespace.Utils.SuperClass”)
}
function DoSomething()
{
::print(“DoSomething()”)
}
}
function FakeNamespace::Utils::SuperClass::DoSomethingElse()
{
::print(“FakeNamespace::Utils::SuperClass::DoSomethingElse()”)
}
local testy = FakeNamespace.Utils.SuperClass();
testy.DoSomething();
testy.DoSomethingElse();
在声明之后,可以通过遵循适用于表的相同规则(operator < – )来添加或修改方法或属性:
//添加新属性
Foo.stuff <- 10;
//修改现有属性的默认值
Foo.testy <- “I’m a string”;
//添加新方法
function Foo::DoSomething(a,b)
{
return a+b;
}
实例化类后,不再可能添加新属性,但可以添加或替换方法。
(9.1.1) 静态变量
Squirrel的类支持静态成员变量。 静态变量在类的所有实例之间共享其值。 通过在变量声明前加上关键字static来声明静态; 声明必须在类里。
注意:静态是只读的。
class Foo {
constructor()
{
//..stuff
}
name = “normal variable”;
//static variable
static classname = “The class name is foo”;
};
(9.1.2) 类属性
类允许将属性与其成员相关联。 属性是一种元数据形式,可用于存储特定于应用程序的信息,如文档字符串,IDE属性,代码生成器等等。类属性通过在成员声明之前在类体中声明,并由符号</ and />。 这是一个例子:
class Foo </ test = “我是类级别属性” />{
</ test = “freakin attribute” /> // PrintTesty 方法的属性
function PrintTesty()
{
foreach(i,val in testy)
{
::print(“idx = “+i+” = “+val+” \n”);
}
}
</ flippy = 10 , second = [1,2,3] /> //testy 成员的属性
testy = null;
}
事实上,属性是一个Table。 对于属性声明,Squirrel使用</ />语法而不是花括号{}来提高可读性。
这意味着适用于Table的所有规则都适用于属性。
可以通过内置函数classobj.getattributes(membername)检索属性(参见内置函数)。 并且可以通过内置函数classobj.setattributes(membername,val)进行修改/添加。
以下代码遍历所有Foo成员的属性:
foreach(member,val in Foo)
{
::print(member+”\n”);
local attr;
if((attr = Foo.getattributes(member)) != null) {
foreach(i,v in attr)
{
::print(“\t”+i+” = “+(typeof v)+”\n”);
}
}
else {
::print(“\t<no attributes>\n”)
}
}
(9.2) 类实例
类对象继承了Table的几个特性,区别在于可以创建同一个类的多个实例。 类实例是一个对象,它共享创建它的表的相同结构,但保持的是自己的值。 类实例化使用函数表示法。 通过调用类对象来创建类实例。 可以想象一个类就像返回类实例的函数一样:
//创建Foo 的新实例
local inst = Foo();
创建类实例时,会使用类声明中指定的相同值初始化其成员。 这些值是浅复制的,即使值是容器或类实例,也不会执行克隆。
注意:
对于C#和Java程序员:
Squirrel不会克隆成员的默认值,也不会为每个实例执行成员声明(如C#或java)。
所以考虑这个例子:
class Foo {
myarray = [1,2,3]
mytable = {}
}
local a = Foo();
local b = Foo();
在上面的代码片段中,两个实例都将引用相同的数组和相同的表。为了实现C#或Java程序员将要遵循的内容,应采取以下方法。
class Foo {
myarray = null
mytable = null
constructor()
{
myarray = [1,2,3]
mytable = {}
}
}
local a = Foo();
local b = Foo();
当一个类定义一个名为”constructor”的方法时,类实例化操作将自动为新创建的实例调用它。 构造函数方法可以有参数,这将影响实例化操作所需的参数数量。 作为普通函数,构造函数可以具有可变数量的参数(使用参数…):
class Rect {
constructor(w,h)
{
width = w;
height = h;
}
x = 0;
y = 0;
width = null;
height = null;
}
// Rect的构造函数有2个参数,所以必须传递2个参数
local rc = Rect(100,100);
创建实例后,可以按照适用于Table的相同规则设置或获取其属性。 函数无法设置。
实例成员无法删除。
可以通过内置函数instance.getclass()检索创建某个实例的类对象(参见内置函数)
运算符instanceof测试类实例是否是某个类的实例:
local rc = Rect(100,100);
if(rc instanceof ::Rect) {
::print(“It’s a rect”);
}
else {
::print(“It isn’t a rect”);
}
注意:
因为如果左表达式不是类,Squirrel 3.x instanceof不会抛出异常,它只会失败
(9.3) 继承
Squirrel的类通过在类声明中添加关键字extends,后跟表达式来支持单继承。 派生类的语法如下:
class SuperFoo extends Foo {
function DoSomething() {
::print(“I’m doing something”);
}
}
声明派生类时,Squirrel首先复制新类中所有基类的成员,然后继续检查声明的其余部分。
派生类继承它的基类的所有成员和属性,如果派生类重写基类函数,则基类实现被隐藏。 通过’base’关键字获取方法,可以访问基类的重写方法。
这是一个例子:
class Foo {
function DoSomething() {
::print(“I’m the base”);
}
};
class SuperFoo extends Foo {
//overridden method
function DoSomething() {
//calls the base method
base.DoSomething();
::print(“I’m doing something”);
}
}
同样的规则适用于构造函数。 构造函数是一个常规函数(除了在构造时自动调用):
class BaseClass {
constructor()
{
::print(“Base constructor\n”);
}
}
class ChildClass extends BaseClass {
constructor()
{
base.constructor();
::print(“Child constructor\n”);
}
}
local test = ChildClass();
可以通过内置方法getbase()检查派生类的基类:
local thebaseclass = SuperFoo.getbase();
注意,因为方法在调用相同对象的方法时没有特殊的保护策略,所以调用同一个类的方法的基类方法最终可能会调用派生类的重写方法。
通过关键字base(如base.MyMethod())中的派生类的方法可以显式调用基类的方法:
class Foo {
function DoSomething() {
::print(“I’m the base”);
}
function DoIt()
{
DoSomething();
}
};
class SuperFoo extends Foo {
//overridden method
function DoSomething() {
::print(“I’m the derived”);
}
function DoIt() {
base.DoIt();
}
}
//creates a new instance of SuperFoo
local inst = SuperFoo();
//prints “I’m the derived”
inst.DoIt();
(9.4) 元方法
类实例允许通过元方法定制其语义的某些方面(参见Metamethods)。 对于C ++程序员:”metamethods的行为大致类似于重载运算符”。 类支持的元方法是
_add, _sub, _mul, _div, _unm, _modulo, _set, _get, _typeof, _nexti, _cmp, _call, _delslot, _tostring
类对象只支持2个元方法: _newmember 和_inherited
以下示例显示如何创建实现元方法的类_add.:
class Vector3 {
constructor(…)
{
if(vargv.len() >= 3) {
x = vargv[0];
y = vargv[1];
z = vargv[2];
}
}
function _add(other)
{
return ::Vector3(x+other.x,y+other.y,z+other.z);
}
x = 0;
y = 0;
z = 0;
}
local v0 = Vector3(1,2,3)
local v1 = Vector3(11,12,13)
local v2 = v0 + v1;
::print(v2.x+”,”+v2.y+”,”+v2.z+”\n”);
从2.1版开始,类支持2个metamethods _inherited和_newmember。 当一个类继承自实现_inherited的类时,会调用_inherited。 为添加到类中的每个成员调用_newmember(在声明时)。
10、Generators生成器
包含yield语句的函数称为”生成器函数”。 当调用生成器函数时,它不执行函数体,而是返回一个新的暂停生成器。 返回的生成器可以在生存时通过resume语句恢复。 yield关键字,暂停生成器的执行,并可选择将表达式的结果返回给恢复生成器的函数。 生成器返回时会死,这可以通过显式返回语句或退出函数体来实现; 如果在生成器运行时发生未处理的异常(或运行时错误),则生成器将自动死亡。 死发生器不能再恢复了:
function geny(n)
{
for(local i=1;i<=n;i+=1)
yield i;
return null;
}
local gtor=geny(10);
local x;
while(x=resume gtor) print(x+”\n”);
该代码的输出将是:
1
2
3
4
5
6
7
8
9
10
也可以使用foreach语句迭代生成器。 当foreach评估生成器时,将在每次迭代时恢复生成器,直到它返回。 return语句返回的值将被忽略。
注意:
暂停的生成器将保存对存储在其局部变量中的所有值的强引用,除了此对象只是弱引用。 正在运行的生成器也对此对象具有强引用。
11、常量和枚举
Squirrel允许将常量值绑定到将在编译时计算的标识符。 这是通过常量和枚举实现的。
(11.1) 常量
常量将特定值绑定到标识符。 常量类似于全局值,除了它们是在编译时计算的,并且它们的值不能更改。
常量值只能是整数,浮点数或字符串文字。 不允许表达。 使用以下语法声明:
const foobar = 100;
const floatbar = 1.2;
const stringbar = “I’m a contant string”;
常量始终是全局范围的,从声明它们的那一刻起,任何后续代码都可以引用它们。 常量将影响具有相同名称的任何全局槽(通过使用::语法,全局槽将保持可见):
local x = foobar * 2;
(11.2) 枚举
作为常量,枚举将特定值绑定到名称。 枚举也在编译时进行评估,其值不能更改。
枚举声明在程序中引入了新的枚举。 枚举值只能是整数,浮点数或字符串文字。 不允许表达:
enum Stuff {
first, //this will be 0
second, //this will be 1
third //this will be 2
}
或
enum Stuff {
first = 10
second = “string”
third = 1.2
}
以与访问静态类成员类似的方式访问枚举值。 必须使用枚举的名称限定成员的名称,例如Stuff.second Enumerations将影响具有相同名称的任何全局槽(使用::语法将保持全局槽可见):
local x = Stuff.first * 2;
(11.3) 实现说明
枚举和常量是编译时功能。 只有整数,字符串和浮点数可以声明为const / enum; 不允许使用表达式(因为它们必须在编译时进行检查)。 声明const或enum时,会将编译时间添加到consttable中。 此表存储在VM共享状态中,并由VM及其所有线程共享。 consttable是一个普通的squirrel 表; 以roottable相同的方式可以修改运行时。 您可以通过内置函数getconsttable()访问consttable,也可以通过内置函数setconsttable()更改它。
这里有一些例子:
//creates a constant
getconsttable()[“something”] <- 10″
//creates an enumeration
getconsttable()[“somethingelse”] <- { a = “10”, c = “20”, d = “200”};
//deletes the constant
delete getconsttable()[“something”]
//deletes the enumeration
delete getconsttable()[“somethingelse”]
该系统允许在程序上声明常量和枚举,也可以将任何squirrel类型分配给常量/枚举(函数,类等…)。 然而,这将使代码块的序列化变得不可能。
12、线程
Squirrel支持协作线程(也称为协同程序)。 协作线程是一个子程序,它可以在执行中期暂停并为调用者提供一个值而不返回程序流,然后它的执行可以在稍后从它被挂起的同一点恢复。 起初看起来Squirrel线程可能与生成器混淆,实际上它们的行为非常相似。 但是,当生成器在调用程序栈中运行并且只能挂起本地栈,线程有自己的执行栈,全局表和错误处理程序; 这允许线程挂起嵌套调用并拥有自己的错误策略。
(12.1) 使用线程
线程是通过内置函数’newthread(func)’创建的;这个函数获取一个squirrel函数作为参数并将其绑定到新的线程objecs(将是线程体)。返回的线程对象最初处于”空闲”状态。线程可以使用’threadobj.call()’函数启动;传递给’call’的参数被传递给线程函数。
一个线程可以被挂起调用函数suspend(),当发生这种情况时,唤醒(或启动)线程返回的函数(如果一个参数传递给suspend()它将是唤醒函数的返回值,如果没有参数传递的返回值将为null)。一个挂起的线程可以恢复调用函数’threadobj.wakeup’,当发生这种情况时,挂起线程的函数将返回(如果参数被传递给wakeup,它将是suspend函数的返回值,如果没有传递参数返回值为null)。
线程在其主函数返回时或在执行期间发生未处理的异常时终止:
function coroutine_test(a,b)
{
::print(a+” “+b+”\n”);
local ret = ::suspend(“suspend 1”);
::print(“the coroutine says “+ret+”\n”);
ret = ::suspend(“suspend 2”);
::print(“the coroutine says “+ret+”\n”);
ret = ::suspend(“suspend 3”);
::print(“the coroutine says “+ret+”\n”);
return “I’m done”
}
local coro = ::newthread(coroutine_test);
local susparam = coro.call(“test”,”coroutine”); //starts the coroutine
local i = 1;
do
{
::print(“suspend passed (“+susparam+”)\n”)
susparam = coro.wakeup(“ciao “+i);
++i;
}while(coro.getstatus()==”suspended”)
::print(“return passed (“+susparam+”)\n”)
该程序的结果将是:
test coroutine
suspend passed (suspend 1)
the coroutine says ciao 1
suspend passed (suspend 2)
the coroutine says ciao 2
suspend passed (suspend 3)
the coroutine says ciao 3
return passed (I’m done).
以下是如何组合线程和尾递归的有趣示例:
function state1()
{
::suspend(“state1”);
return state2(); //tail call
}
function state2()
{
::suspend(“state2”);
return state3(); //tail call
}
function state3()
{
::suspend(“state3”);
return state1(); //tail call
}
local statethread = ::newthread(state1)
::print(statethread.call()+”\n”);
for(local i = 0; i < 10000; i++)
::print(statethread.wakeup()+”\n”);
13、弱引用
弱引用允许程序员创建对象的引用,而不会影响对象本身的生命周期。 在squirrel中,弱引用是通过内置方法obj.weakref()创建的第一类对象。 除null之外的所有类型都实现了weakref()方法; 但是在bools,integer和float中,该方法只返回对象本身(这是因为这些类型总是按值传递)。 将弱引用分配给容器时(表槽,数组,类或实例)的处理方式与其他对象不同; 当获取持有弱引用的容器槽时,它总是返回弱引用而不是弱引用对象指向的值。这允许程序员忽略处理的值很弱的事实。 当弱引用指向的对象被销毁时,弱引用自动设置为null:
local t = {}
local a = [“first”,”second”,”third”]
//creates a weakref to the array and assigns it to a table slot
t.thearray <- a.weakref();
表槽’thearray’包含对数组的弱引用。 以下行打印”first”,因为表(和所有其他容器)总是返回弱ref指向的对象:
print(t.thearray[0]);
对数组的唯一强引用是由局部变量’a’拥有的,因为下面的行为’a’分配一个整数,数组被销毁:
a = 123;
当弱ref引用的对象被破坏时,弱ref会自动设置为null,因此以下行将打印”null”:
::print(typeof(t.thearray))
(13.1) 明确处理弱引用
如果将弱引用分配给局部变量,则将其视为任何其他值:
local t = {}
local weakobj = t.weakref();
以下行打印”weakref”:
::print(typeof(weakobj))
weakref指向的对象可以通过内置方法weakref.ref()获得。
以下行打印”table”:
::print(typeof(weakobj.ref()))
14、委托
Squirrel支持隐式委托。 每个table或userdata都可以有一个父表(委托)。 父表是一个普通表,允许为他的子定义特殊行为。 当table(或userdata)使用与其中一个槽不对应的键索引时,解释器会自动将get(或set)操作委托给其父槽:
Entity <- {
}
function Entity::DoStuff()
{
::print(_name);
}
local newentity = {
_name=”I’m the new entity”
}
newentity.setdelegate(Entity)
newentity.DoStuff(); //prints “I’m the new entity”
可以通过内置方法table.getdelegate()获取表的委托:
local thedelegate = newentity.getdelegate();
15、Metamethods 元方法
Metamethods是一种允许定制语言语义的某些方面的机制。 这些方法是放在父表(委托)或类声明中的普通函数; 可以通过定义元方法来更改表/类实例行为的许多方面。 类对象(非实例)仅支持2个元方法_newmember,_inherited。
例如,当我们在2个表上使用”==”以外的关系运算符时,VM将检查表中是否在其父级中有一个名为”_cmp”的方法,如果是这样,它将调用它来确定表之间的关系:
local comparable={
_cmp = function (other)
{
if(name<other.name)return -1;
if(name>other.name)return 1;
return 0;
}
}
local a={ name=”Alberto” }.setdelegate(comparable);
local b={ name=”Wouter” }.setdelegate(comparable);
if(a>b)
print(“a>b”)
else
print(“b<=a”);
对于类,前面的代码变为:
class Comparable {
constructor(n)
{
name = n;
}
function _cmp(other)
{
if(name<other.name) return -1;
if(name>other.name) return 1;
return 0;
}
name = null;
}
local a = Comparable(“Alberto”);
local b = Comparable(“Wouter”);
if(a>b)
print(“a>b”)
else
print(“b<=a”);
(15.1) _set
_set(idx,val)
当索引idx不存在于对象或其委托链中时调用。 _set必须’throw null’来通知没有找到key但是没有运行时错误(清除失败)。 这允许程序在运行时错误和”未找到索引”之间进行区分。
(15.2) _get
_get(idx,val)
当索引idx不存在于对象或其委托链中时调用。 _get必须’throw null’来通知没有找到key但是没有运行时错误(清除失败)。 这允许程序在运行时错误和”未找到索引”之间进行区分。
(15.3) _newslot
_newslot(key,value)
当脚本尝试在表中添加新插槽时调用。
如果插槽已经存在于目标表中,则不会调用该方法,且使用”new slot”操作符
(15.4) _delslot
_delslot(key)
当脚本从表中删除插槽时调用。 如果调用该方法squirrel不会尝试删除自己的插槽
(15.5) _add
_add(other)
the + 操作符
返回 this + other
(15.6) _sub
_sub(other)
– 操作符 (类似 _add)
(15.7) _mul
_mul(other)
* 操作符 (类似 _add)
(15.8) _div
_div(other)
/ 操作符 (类似 _add)
(15.9) _modulo
_modulo(other)
% 操作符 (类似 _add)
(15.10) _unm
_unm()
一元减号运算符
(15.11) _tyoeof
_tyoeof()
在表由typeof运算符,userdata和类实例上调用
将此类型作为字符串返回
(15.12) _cmp
_cmp(other)
调用以模拟<> <=> =和<=>运算符
返回一个整数,如下所示:
返回 | 关系 |
> 0 | if this > other |
0 | if this == other |
< 0 | if this < other |
(15.13) _call
_call(other)
调用table,userdata或类实例时调用
(15.14) _cloned
_cloned(original)
克隆表或类实例时调用(在克隆表中)
(15.15) _nexti
_nexti(previdx)
当foreach循环迭代userdata或类实例时调用
如果previdx == null,则表示它是第一次迭代。 该函数必须返回’next’值的索引。
(15.16) _tostring
_tostring(previdx)
在字符串连接期间或打印函数打印表,实例或用户数据时调用。也由sq_tostring()api调用
必须返回对象的字符串表示形式。
(15.17) _inherited
_inherited(attributes)
当一个类对象继承自实现_inherited的类时,调用this包含新类。
返回值被忽略。
(15.18) _newmember
_newmember(index,value,attributes,isstatic)
为类体中声明的每个成员调用(在声明时)。
如果实现该功能,则不会将成员添加到该类中。
16、内置函数
(16.1) 全局符号
array(size[, fill])
创建并返回指定大小的数组。如果指定了可选参数fill,则其值将用于填充新数组的插槽。 如果省略填充参数,则使用null。
seterrorhandler(func)
设置运行时错误处理程序
callee()
返回当前运行的闭包
setdebughook(hook_func)
设置调试钩子
enabledebuginfo(enable)
在编译时启用/禁用调试行信息生成。 enable != null启用。 enable == null 禁用。
getroottable()
返回VM的根表。
setroottable(table)
设置VM的根表。 并返回上一个根表。
getconsttable()
返回VM的常量表。
setconsttable(table)
设置VM的常量表。 并返回前一个常量表。
assert(exp)
如果exp为null,则抛出异常
print(x)
在标准输出中打印x
error(x)
在标准错误输出中打印x
compilestring(string[, buffername])
将包含squirrel脚本的字符串编译到函数中并返回它:
local compiledscript=compilestring(“::print(\”ciao\”)”);
//run the script
compiledscript();
collectgarbage()
运行垃圾收集器并返回找到(和删除)的引用循环数此函数仅适用于垃圾收集器构建。
resurrectunreachable()
运行垃圾收集器并返回包含找到的所有无法访问的对象的数组。 如果找不到无法访问的对象,则返回null。 此功能旨在帮助调试参考周期。 此函数仅适用于垃圾收集器构建。
type(obj)
返回对象的’raw’类型而不调用metatmethod’_typeof’。
getstackinfos(level)
返回给定调用堆栈级别的堆栈信息。 返回一个格式如下的表:
{
func=”DoStuff”, //function name
src=”test.nut”, //source file
line=10, //line number
locals = { //a table containing the local variables
a=10,
testy=”I’m a string”
}
}
level = 0是当前函数,level = 1是调用者,依此类推。 如果堆栈级别不存在,则该函数返回null。
newthread(threadfunc)
创建一个新的协作线程对象(协同程序)并返回它
_versionnumber_
描述VM和编译器版本的整数值。 例如。 对于Squirrel 3.0.1,此值为301
_version_
描述VM和编译器版本的字符串值。
_charsize_
字符的内部VM表示的字符大小(对于UNICODE构建为2,ASCII构建为1)。
_intsize_
内部VM表示整数的大小以字节为单位(4位为32位构建,8位为64位构建)。
_floatsize_
内部VM表示浮点数的大小(以字节为单位)(对于双精度构建为8,单精度构建为4)。
(16.1.1) 默认委托
除了null和userdata之外,每个squirrel对象都有一个默认委托,其中包含一组函数来操作和检索来自对象本身的信息。
(16.2) Integer整数
integer.tofloat()
将数字转换为float并返回它
integer.tostring()
将数字转换为字符串并返回它
integer.tointeger()
返回整数的值(虚函数)
integer.tochar()
返回包含由整数表示的单个字符的字符串。
integer.weakref()
虚函数,返回整数本身。
(16.3) Float整数
float.tofloat()
返回float的值(虚函数)
float.tointeger()
将数字转换为整数并返回它
float.tostring()
将数字转换为字符串并返回它
float.tochar()
返回一个字符串,其中包含由float的整数部分表示的单个字符。
float.weakref()
虚函数,返回浮点数本身。
(16.4) Bool 逻辑
bool.tofloat()
返回1.0表示true为0.0表示false
bool.tointeger()
返回1表示true为0表示false
bool.tostring()
返回”true”表示true为”false”表示false
bool.weakref()
虚函数,返回bool本身。
(16.5) String 文本
string.len()
返回字符串长度
string.tointeger([base])
将字符串转换为整数并返回它。可以指定可选参数base,如果未指定base,则默认为base 10
string.tofloat()
将字符串转换为float并返回它
string.tostring()
返回字符串(虚函数)
string.slice(start[, end])
返回字符串的一部分作为新字符串。复制从start到end(不包含)。 如果start为负,则索引计算为length + start,如果end为负,则索引计算为length + end。 如果省略end,则end等于字符串长度。
string.find(substr[, startidx])
从索引startidx开始搜索子字符串(substr)并返回其第一次出现的索引。 如果省略startidx,则搜索操作从字符串的开头开始。 如果未找到substr,则该函数返回null。
string.tolower()
返回字符串的小写副本。
string.toupper()
返回字符串的大写副本。
string.weakref()
返回对象的弱引用。
(16.6) Table 表
table.len()
返回表中包含的槽数
table.rawget(key)
尝试从插槽’key’获取值而不使用委托
table.rawset(key, val)
使用值’val’设置插槽’key’而不使用委托。 如果插槽不存在,则会创建该插槽。
table.rawdelete()
删除槽key而不使用委托并返回值。 如果slo不存在则返回null。
table.rawin(key)
如果插槽’key’存在,则返回true。 该函数与运算符’in’具有相同的eddect,但不使用委托。
table.weakref()
返回对象的弱引用。
table.tostring()
尝试调用_tostring元方法,如果失败。 返回”(table:pointer)”。
table.clear()
从表中删除所有插槽
table.setdelegate(table)
设置表的委托,删除委托必须传递’null’给该函数。 该函数返回表本身(例如,在这种情况下,a.setdelegate(b)’a’是返回值)。
table.getdelegate()
返回表的委托,如果没有设置委托,则返回null。
(16.7) Array 数组
array.len()
返回数组的长度
array.append(val)
在数组的末尾追加值’val’
array.push(val)
在数组的末尾追加值’val’
array.extend(array)
通过附加给定数组中的所有项来扩展数组。
array.pop()
从数组后面删除一个值并返回它。
array.top()
返回索引最高的数组的值
array.insert(idx, val)
在数组中的’idx’位置插入值’val’
array.remove(idx)
删除数组中’idx’位置的值
array.resize(size[, fill])
调整数组的大小,如果指定了可选参数fill,则其值将用于填充新数组的插槽(如果指定的大小大于先前的大小)。 如果省略填充参数,则使用null。
array.sort([compare_func])
对数组进行排序。 可以选择性地传递自定义比较函数。函数原型如下:
function custom_compare(a,b)
{
if(a>b) return 1
else if(a<b) return -1
return 0;
}
可以使用lambda表达式和运算符<=>编写更紧凑的自定义比较版本
arr.sort(@(a,b) a <=> b);
array.reverse()
将数组的元素反转
array.slice(start[, end])
返回数组的一部分作为新数组。 从开始到结束复制(不包括在内)。 如果start为负,则索引计算为length + start,如果end为负,则索引计算为length + end。 如果省略end,则end等于数组长度。
array.weakref()
返回对象的弱引用。
array.tostring()
返回字符串”(array:pointer)”。
array.clear()
从数组中删除所有项目
array.map(func(a))
创建一个相同大小的新数组。 对于原始数组中的每个元素,调用函数’func’并将函数的返回值赋给新创建的数组的相应元素。
array.apply(func(a))
对于数组中的每个元素,调用函数’func’并将该元素的原始值替换为函数的返回值。
array.reduce(func(prevval, curval))
将数组减少为单个值。 对于数组中的每个元素,调用函数’func’传递初始值(或前一个回调调用的值)和当前元素的值。 然后,函数的返回值用作下一个元素的”prevval”。 给定长度为0的数组,返回null。 给定长度为1的数组,返回第一个元素。 给定一个包含2个或更多元素的数组,调用前两个元素作为参数的函数,得到该结果,然后用该结果和第三个元素调用函数,得到该结果,用该结果调用函数和第四个参数 依此类推,直到所有元素都被处理完毕。 最后返回func的最后一次调用的返回值。
array.filter(func(index, val))
创建一个新数组,其中包含通过所提供函数实现的测试的所有元素。 详细地说,它创建一个新数组,原始数组中的每个元素都调用指定的函数传递元素的索引及其值; 如果函数返回’true’,则在新创建的数组上添加相应元素的值。
array.find(value)
对数组中的值执行线性搜索。 如果找到null,则返回值的索引。
(16.8) Function 函数
function.call(_this, args…)
使用指定的环境对象(’this’)和参数调用该函数
function.pcall(_this, args…)
使用指定的环境对象(’this’)和参数调用该函数,如果发生错误,该函数将不会调用错误回调(pcall保留为’protected call’)
function.acall(array_args)
使用指定的环境对象(’this’)和参数调用该函数。 该函数接受一个包含将传递给被调用函数的参数的数组。其中array_args必须在[0]位置包含所需的’this’对象。
function.pacall(array_args)
使用指定的环境对象(’this’)和参数调用该函数。 该函数接受一个包含将传递给被调用函数的参数的数组。其中array_args必须在[0]位置包含所需的’this’对象。 如果发生错误,此函数将不会调用错误回调(pacall保留为”受保护的数组调用”)
function.weakref()
返回对象的弱引用。
function.tostring()
返回字符串”(closure:pointer)”。
function.setroot(table)
设置闭包的根表
function.getroot()
返回闭包的根表
function.bindenv(env)
克隆函数(也称为闭包)并将环境对象绑定到它(表,类或实例)。 新创建函数的this参数将始终设置为env。 请注意,创建的函数包含对其环境对象的弱引用,因此不能用于控制其生命周期。
function.getinfos()
返回一个包含函数信息的表,如参数,名称和源名称;
//the data is returned as a table is in form
//pure squirrel function
{
native = false
name = “zefuncname”
src = “/somthing/something.nut”
parameters = [“a”,”b”,”c”]
defparams = [1,”def”]
varargs = 2
}
//native C function
{
native = true
name = “zefuncname”
paramscheck = 2
typecheck = [83886082,83886384] //this is the typemask (see C defines OT_INTEGER,OT_FLOAT etc…)
}
(16.9) Class 类
class.instance()
返回该类的新实例。 此函数不会调用实例构造函数。 必须显式调用构造函数(例如,class_inst.constructor(class_inst))。
class.getattributes(membername)
返回指定成员的属性。 如果参数成员为null,则该函数返回类级别属性。
class.setattributes(membername, attr)
设置指定成员的属性并返回先前的属性值。 如果参数成员为null,则该函数设置类级别属性。
class.rawin(key)
如果插槽’key’存在,则返回true。 该函数与运算符’in’具有相同的eddect,但不使用委托。
class.weakref()
返回对象的弱引用。
class.tostring()
返回字符串 “(class : pointer)”.
class.rawget(key)
尝试从插槽’key’获取值而不使用委托
class.rawset(key, val)
使用值’val’设置插槽’key’而不使用委托。 如果插槽不存在,则会创建该插槽。
class.newmember(key, val[, attrs][, bstatic])
使用值’val’和属性’attrs’设置/添加插槽’key’,如果存在,则调用_newmember metamethod。 如果bstatic为true,则插槽将添加为静态。 如果插槽不存在,则会创建该插槽。
class.rawnewmember(key, val[, attrs][, bstatic])
设置/添加插槽’key’的值为’val’,属性’attrs’。如果bstatic为true,则插槽将被添加为静态。 如果插槽不存在,则会创建该插槽。 它不会调用任何元方法。
(16.10) Class Instance 类实例
instance.getclass()
返回创建实例的类。
instance.rawin(key)
如果插槽’key’存在,则返回true。 该函数与运算符’in’具有相同的eddect,但不使用委托。
instance.weakref()
返回对象的弱引用。
instance.tostring()
尝试调用_tostring元方法,如果失败。 返回”(insatnce:pointer)”。
instance.rawget(key)
尝试从插槽’key’获取值而不使用委托
instance.rawset(key, val)
使用值’val’设置插槽’key’而不使用委托。 如果插槽不存在,则会创建该插槽。
(16.11) Generator 生成器
generator.getstatus()
以字符串形式返回生成器的状态:”running”,”dead”或”suspended”。
generator.weakref()
返回对象的弱引用。
generator.tostring()
返回字符串”(generator:pointer)”。
(16.12) Thread 线程
thread.call(…)
使用指定的参数启动线程
thread.wakeup([wakeupval])
唤醒挂起的线程,接受一个可选参数,该参数将用作挂起线程的函数的返回值(通常为suspend())
thread.wakeupthrow(objtothrow[, propagateerror = true])
唤醒一个被挂起的线程,在唤醒线程中抛出异常,抛出对象’objtothrow’。
thread.getstatus()
返回线程的状态(”idle”,”running”,”suspended”)
thread.weakref()
返回对象的弱引用。
thread.tostring()
返回字符串”(thread:pointer)”。
thread.getstackinfos(stacklevel)
返回给定栈级别的栈帧信息(0是当前函数1是调用者,依此类推)。
(16.13) Weak Reference 弱引用
weakreference.ref()
返回弱引用指向的对象,如果指向的对象被销毁,则返回null。
weakreference.weakref()
返回对象的弱引用。
weakreference.tostring()
返回字符串”(weakref:pointer)”。
API 引用
1、虚拟机
sq_close
void sq_close(HSQUIRRELVM v)
Parameters: v (HSQUIRRELVM) – 目标VM
释放一个squirrel VM和所有相关的友元VM
sq_geterrorfunc
SQPRINTFUNCTION sq_geterrorfunc(HSQUIRRELVM v)
Parameters: v (HSQUIRRELVM) – the target VM
Returns: 指向SQPRINTFUNCTION的指针,如果未设置任何函数,则为NULL。
sq_getforeignptr
SQUserPointer sq_getforeignptr(HSQUIRRELVM v)
Parameters: v (HSQUIRRELVM) – 目标 VM
Returns: 当前VMs外部指针。
返回VM实例的外部指针。
sq_getprintfunc
SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v)
Parameters: v (HSQUIRRELVM) – 目标 VM
Returns: 指向SQPRINTFUNCTION的指针,如果未设置任何函数,则为NULL。
sq_getsharedforeignptr
SQUserPointer sq_getsharedforeignptr(HSQUIRRELVM v)
Parameters: v (HSQUIRRELVM) – 目标VM
Returns: 当前VM共享外部指针
sq_getprintfunc
SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v)
Parameters: |
|
Returns: | 指向SQPRINTFUNCTION的指针,如果未设置任何函数,则为NULL。 |
返回给定虚拟机的当前打印功能。 (参见sq_setprintfunc())
sq_getsharedforeignptr
SQUserPointer sq_getsharedforeignptr(HSQUIRRELVM v)
Parameters: |
|
Returns: | 当前VM共享外部指针 |
返回一组朋友VM的共享外部指针。
sq_getsharedreleasehook
SQUserPointer sq_getsharedreleasehook(HSQUIRRELVM v)
Parameters: v (HSQUIRRELVM) – 目标VM
Returns: 当前的VM释放钩子。
返回一组朋友VM的共享释放钩子。
sq_getversion
SQInteger sq_getversion()
Returns: vm的版本号(如SQUIRREL_VERSION_NUMBER中所示)。
返回vm的版本号。
sq_getvmreleasehook
SQUserPointer sq_getvmreleasehook(HSQUIRRELVM v)
Parameters: |
|
Returns: | 当前 VMs 释放钩子. |
返回VM实例的释放钩子。
sq_getvmstate
SQInteger sq_getvmstate(HSQUIRRELVM v)
Parameters: |
|
Returns: | vm的状态编码为整数值。 定义了以下常量:SQ_VMSTATE_IDLE,SQ_VMSTATE_RUNNING,SQ_VMSTATE_SUSPENDED。 |
返回虚拟机的执行状态
sq_move
void sq_move(HSQUIRRELVM dest, HSQUIRRELVM src, SQInteger idx)
Parameters:
dest (HSQUIRRELVM) – 目标 VM
src (HSQUIRRELVM) – 源 VM
idx (SQInteger) – 源栈中的索引移动的值
将源栈的位置”idx”的值压入到目标栈中
sq_newthread
HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, SQInteger initialstacksize)
Parameters: |
|
Returns: | 指向新VM的指针。 |
Remarks: | 默认情况下,roottable与作为第一个参数传递的VM共享。 新的VM生命周期绑定到栈中压入的”线程”对象,其行为类似于普通的squirrel对象。 |
创建一个新的vm friendvm作为第一个参数传递的那个,并将其作为”线程”对象压入到栈中。
sq_open
HSQUIRRELVM sq_open(SQInteger initialstacksize)
Parameters: |
|
Returns: | 一个 squirrel 虚拟机句柄 |
Remarks: | 返回的VM必须与sq_releasevm一起释放 |
创建一个包含在新执行栈中的squirrel VM的新实例。
sq_pushconsttable
void sq_pushconsttable(HSQUIRRELVM v)
Parameters: v (HSQUIRRELVM) – 目标 VM
将当前常量表压入到栈中
sq_pushregistrytable
void sq_pushregistrytable(HSQUIRRELVM v)
Parameters: v (HSQUIRRELVM) – 目标 VM
将注册表压入到栈中
sq_pushroottable
void sq_pushroottable(HSQUIRRELVM v)
Parameters: v (HSQUIRRELVM) – 目标 VM
将当前根表压入到栈中
sq_setconsttable
void sq_setconsttable(HSQUIRRELVM v)
Parameters: v (HSQUIRRELVM) – 目标 VM
从栈弹出一个表并将其设置为const表
sq_seterrorhandler
void sq_seterrorhandler(HSQUIRRELVM v)
Parameters: |
|
Remarks: | 错误处理程序由友元VM共享 |
从栈弹出一个闭包或本机闭包,并将其设置为运行时错误处理程序。
sq_setforeignptr
void sq_setforeignptr(HSQUIRRELVM v, SQUserPointer p)
Parameters: v (HSQUIRRELVM) – 目标VM
p (SQUserPointer) – 必须设置的指针
设置某个VM实例的外部指针。 外部指针是与VM关联的任意用户定义指针(默认情况下为值id 0)。 VM忽略该指针。
sq_setprintfunc
void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc, SQPRINTFUNCTION errorfunc)
Parameters: |
|
Remarks: | print func具有以下原型:
void printfunc(HSQUIRRELVM v,const SQChar *s,…) |
设置虚拟机的打印功能。 内置函数’:: print()’使用此函数输出文本。
sq_setroottable
void sq_setroottable(HSQUIRRELVM v)
Parameters: v (HSQUIRRELVM) – 目标 VM
从栈中弹出一个表并将其设置为根表
sq_setsharedforeignptr
void sq_setsharedforeignptr(HSQUIRRELVM v, SQUserPointer p)
Parameters: |
|
设置共享外部指针。 外部指针是与一组友元VM相关联的任意用户定义指针(默认情况下是值id 0)。 使用sq_open()创建”主”VM后,使用sq_newthread创建的所有友元VM共享相同的共享指针。
sq_setsharedreleasehook
void sq_setsharedreleasehook(HSQUIRRELVM v, SQRELESEHOOK hook)
Parameters: |
|
设置某个VM组的释放钩子。 当组vm的最后一个vm被销毁时(通常在调用sq_close()时),将调用release钩子。 传递给函数的userpointer是共享的外部指针(请参阅sq_getsharedforeignptr())。 使用sq_open()创建”主”VM后,使用sq_newthread()创建的所有友元VM共享相同的共享释放钩子。
sq_setvmreleasehook
void sq_setvmreleasehook(HSQUIRRELVM v, SQRELESEHOOK hook)
Parameters: v (HSQUIRRELVM) – 目标 VM
hook (SQRELESEHOOK) – 设置的钩子
设置某个VM实例的释放钩子。 当vm被销毁时,将调用释放钩子。 传递给函数的userpointer是vm foreignpointer(参见sq_setforeignpointer())
sq_suspendvm
HRESULT sq_suspendvm(HSQUIRRELVM v)
Parameters: |
|
Returns: | 一个SQRESULT(由C函数返回) |
Remarks: | sq_result只能作为C函数的返回表达式调用。 该功能将失败是通过更多C调用或元方法完成暂停。 |
暂停执行指定的vm。
SQInteger suspend_vm_example(HSQUIRRELVM v)
{
return sq_suspendvm(v);
}
sq_wakeupvm
HRESULT sq_wakeupvm(HSQUIRRELVM v, SQBool resumedret, SQBool retval, SQBool raiseerror, SQBool throwerror)
Parameters: |
|
Returns: | HRESULT. |
唤醒执行先前挂起的虚拟机。
2、编译
sq_compile
SQRESULT sq_compile(HSQUIRRELVM v, HSQLEXREADFUNC read, SQUserPointer p, const SQChar * sourcename, SQBool raiseerror)
Parameters: |
|
Returns: | 返回SQRESULT。 如果sq_compile失败,则不会在栈中压入任何内容。 |
Remarks: | 如果出现错误,该函数将调用sq_setcompilererrorhandler()设置的函数。 |
编制一个松鼠程序; 如果成功,则将编译后的脚本作为函数压入到栈中。
sq_compilebuffer
SQRESULT sq_compilebuffer(HSQUIRRELVM v, const SQChar* s, SQInteger size, const SQChar * sourcename, SQBool raiseerror)
Parameters: |
|
Returns: | 返回SQRESULT。 如果sq_compile失败,则不会在栈中压入任何内容。 |
Remarks: | 如果出现错误,该函数将调用sq_setcompilererrorhandler()设置的函数。 |
从内存缓冲区编译一个松鼠程序; 如果成功,则将编译后的脚本作为函数压入到栈中。
sq_enabledebuginfo
void sq_enabledebuginfo(HSQUIRRELVM v, SQBool enable)
Parameters: |
|
Remarks: | 该函数也会影响所有线程。 |
在编译时启用/禁用调试行信息生成。
sq_notifyallexceptions
void sq_notifyallexceptions(HSQUIRRELVM v, SQBool enable)
Parameters: |
|
Remarks: | 默认情况下,仅当未处理异常(调用栈中不存在try / catch)时,VM才会调用错误回调。 如果启用了notifyallexceptions,则即使在try / catch块之间,VM也会针对任何异常调用错误回调。 此功能对于实现调试器很有用。 |
启用/禁用已处理异常的错误回调通知。
sq_setcompilererrorhandler
void sq_setcompilererrorhandler(HSQUIRRELVM v, SQCOMPILERERROR f)
Parameters: |
|
Remarks: | 如果参数f为NULL,则在编译器错误发生时不会调用函数。 编译器错误处理程序在友元VM之间共享. |
设置编译器错误处理函数
3、栈操作
sq_cmp
SQInteger sq_cmp(HSQUIRRELVM v)
Parameters: |
|
Returns: | > 0 if obj1>obj2 |
Returns: | == 0 if obj1==obj2 |
Returns: | < 0 if obj1<obj2 |
比较栈中的2个对象并进行比较。
sq_gettop
SQInteger sq_gettop(HSQUIRRELVM v)
Parameters: v (HSQUIRRELVM) – 目标 VM
Returns: 一个整数,表示栈顶部的索引
返回栈顶部的索引
sq_pop
void sq_pop(HSQUIRRELVM v, SQInteger nelementstopop)
Parameters: |
|
弹出栈中的n个元素
sq_poptop
void sq_poptop(HSQUIRRELVM v)
Parameters: v (HSQUIRRELVM) –目标VM
从栈中弹出1个对象
sq_push
void sq_push(HSQUIRRELVM v, SQInteger idx)
Parameters: v (HSQUIRRELVM) – 目标 VM
idx (SQInteger) – 栈中的索引要压入的值
将索引idx中的值压入栈
sq_remove
void sq_remove(HSQUIRRELVM v, SQInteger idx)
Parameters: v (HSQUIRRELVM) – 目标 VM
idx (SQInteger) – 要删除的元素的索引
从栈中的任意位置移除元素
sq_reservestack
SQRESULT sq_reservestack(HSQUIRRELVM v, SQInteger nsize)
Parameters: |
|
Returns: | SQRESULT |
重置栈大小,确保剩余的栈空间至少是指定的大小。如果栈较小,它将自动增长。 如果当前正在运行memtamethod函数将失败并且栈将不会调整大小,则此情况必须被视为”栈溢出”。
sq_settop
void sq_settop(HSQUIRRELVM v, SQInteger v)
Parameters: |
|
调整栈大小,如果new top更大,那么当前顶部函数将压入空值。
4、对象创建和处理
sq_bindenv
SQRESULT sq_bindenv(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Returns: | SQRESULT |
Remarks: | 克隆的闭包将环境对象保存为弱引用 |
从栈中弹出一个对象(必须是表,实例或类)克隆栈中位置idx处的闭包,并将弹出的对象设置为克隆闭包的环境。 然后将新的克隆闭包压入栈顶部。
sq_createinstance
SQRESULT sq_createinstance(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Returns: | SQRESULT |
Remarks: | 该函数不会调用实例构造函数。 要创建实例并自动调用其构造函数,必须使用sq_call。 |
在栈中的”idx”位置创建类的实例。 新类实例被压入到栈顶部。
sq_getbool
SQRESULT sq_getbool(HSQUIRRELVM v, SQInteger idx, SQBool * b)
Parameters: |
|
Returns: | SQRESULT |
获取在栈中索引位置的Bool值。
sq_getbyhandle
SQRESULT sq_getbyhandle(HSQUIRRELVM v, SQInteger idx, HSQMEMBERHANDLE* handle)
Parameters: |
|
Returns: | SQRESULT |
使用成员句柄压入类或实例成员的值(请参阅sq_getmemberhandle)
sq_getclosureinfo
SQRESULT sq_getclosureinfo(HSQUIRRELVM v, SQInteger idx, SQUnsignedInteger * nparams, SQUnsignedInteger * nfreevars)
Parameters: |
|
Returns: | SQRESULT |
从squirrel闭包中获取参数的数量和自由变量的数量。
sq_getclosurename
SQRESULT sq_getclosurename(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Returns: | SQRESULT |
压入在栈中的位置索引处闭包的名称。 请注意,如果闭包是匿名的,则名称可以是字符串,也可以是null,或者没有为其指定名称的本机闭包。
sq_getclosureroot
SQRESULT sq_getclosureroot(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Returns: | SQRESULT |
压入在栈中的位置索引处闭包的根表
sq_getfloat
SQRESULT sq_getfloat(HSQUIRRELVM v, SQInteger idx, SQFloat * f)
Parameters: |
|
Returns: | SQRESULT |
获取浮点数在栈中的idx位置。
sq_gethash
SQHash sq_gethash(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Returns: | 栈中位置idx处的值的哈希键 |
Remarks: | 哈希值函数与VM使用的相同。 |
返回栈中idx位置的值的哈希键。
sq_getinstanceup
SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer * up, SQUSerPointer typetag)
Parameters: |
|
Returns: | SQRESULT |
获取栈中位置idx处的类实例的用户指针。 如果参数’typetag’不是0,则该函数检查实例的类或基类是否用指定的标记标记; 如果不是该函数失败。 如果’typetag’为0,该函数将忽略标记检查。
sq_getinteger
SQRESULT sq_getinteger(HSQUIRRELVM v, SQInteger idx, SQInteger * i)
Parameters: |
|
Returns: | SQRESULT |
获取栈中idx位置的整数值。
sq_getmemberhandle
SQRESULT sq_getmemberhandle(HSQUIRRELVM v, SQInteger idx, HSQMEMBERHANDLE* handle)
Parameters: |
|
Returns: | SQRESULT |
Remarks: | 此方法仅适用于类和实例。 通过类获取的句柄稍后可用于设置或从其中一个类实例获取值,反之亦然。 从基类检索的句柄在派生类中仍然有效并且尊重继承规则。 |
从栈中弹出一个值并将其用作索引来获取类成员的句柄。 该句柄稍后可用于使用sq_getbyhandle(),sq_setbyhandle()设置或获取成员值。
sq_getreleasehook
SQRELEASEHOOK sq_getreleasehook(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Remarks: | 如果位置idx的对象不是userdata,类实例或类,则该函数返回NULL。 |
获取栈中位置idx处的userdata,类实例或类的release钩子。
sq_getscratchpad
SQChar * sq_getscratchpad(HSQUIRRELVM v, SQInteger minsize)
Parameters: |
|
Remarks: | 缓冲区有效,直到下一次调用sq_getscratchpad |
返回一个指向内存缓冲区的指针,该缓冲区至少与minsize一样大。
sq_getsize
SQObjectType sq_getsize(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Returns: | 栈中位置idx处的值的大小 |
Remarks: | 此函数仅适用于字符串,数组,表,类,实例和userdata,如果该值不是有效类型,则函数将返回-1。 |
返回栈中idx位置的值的大小,如果值是类或类实例,则返回的大小是userdata缓冲区的大小(请参阅sq_setclassudsize)。
sq_getstring
SQRESULT sq_getstring(HSQUIRRELVM v, SQInteger idx, const SQChar ** c)
Parameters: |
|
Returns: | SQRESULT |
获取指向栈中idx位置的字符串的指针。
sq_getthread
SQRESULT sq_getthread(HSQUIRRELVM v, SQInteger idx, HSQUIRRELVM* v)
Parameters: |
|
Returns: | SQRESULT |
获取一个线程指针在栈中idx位置。
sq_gettype
SQObjectType sq_gettype(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Returns: | 栈中位置idx处的值的类型 |
返回栈中位置idx处的值的类型
sq_gettypetag
SQRESULT sq_gettypetag(HSQUIRRELVM v, SQInteger idx, SQUserPointer * typetag)
Parameters: |
|
Returns: | SQRESULT |
Remarks: | 该函数也适用于实例。 如果目标对象是实例,则获取其基类的typetag。 |
获取栈中位置idx处的对象(userdata或类)的typetag。
sq_getuserdata
SQRESULT sq_getuserdata(HSQUIRRELVM v, SQInteger idx, SQUserPointer * p, SQUserPointer * typetag)
Parameters: |
|
Returns: | SQRESULT |
获取指向栈中idx位置的userdata值的指针。
sq_getuserpointer
SQRESULT sq_getuserpointer(HSQUIRRELVM v, SQInteger idx, SQUserPointer * p)
Parameters: |
|
Returns: | SQRESULT |
获取栈中idx位置的userpointer的值。
sq_newarray
void sq_newarray(HSQUIRRELVM v, SQInteger size)
Parameters: |
|
创建一个新数组并将其压入栈.
sq_newclass
SQRESULT sq_newclass(HSQUIRRELVM v, SQBool hasbase)
Parameters: |
|
Returns: | SQRESULT |
创建一个新的类对象。 如果参数’hasbase’不等于0,则该函数从栈中弹出一个类,并从中继承新创建的类。
sq_newclosure
void sq_newclosure(HSQUIRRELVM v, HSQFUNCTION func, SQInteger nfreevars)
Parameters: |
|
创建一个新的本机闭包,弹出n值将它们设置为新闭包的自由变量,并在栈中压入新闭包。
create a new native closure, pops n values set those as free variables of the new closure, and push the new closure in the stack.
sq_newtable
void sq_newtable(HSQUIRRELVM v)
Parameters: |
|
创建一个新表并将其压入栈
sq_newtableex
void sq_newtableex(HSQUIRRELVM v, SQInteger initialcapacity)
Parameters: |
|
创建一个新表并将其压入栈。 此函数允许指定表的初始容量,以便在创建时知道所需的插槽数时防止不必要的重新散列。
sq_newuserdata
SQUserPointer sq_newuserdata(HSQUIRRELVM v, SQUnsignedInteger size)
Parameters: |
|
创建一个新的userdata并将其压入到栈中
sq_pushbool
void sq_pushbool(HSQUIRRELVM v, SQBool b)
Parameters: |
|
将一个bool压入栈
sq_pushfloat
void sq_pushfloat(HSQUIRRELVM v, SQFloat f)
Parameters: |
|
将一个float压入栈
sq_pushinteger
void sq_pushinteger(HSQUIRRELVM v, SQInteger n)
Parameters: |
|
将一个integer压入栈
sq_pushnull
void sq_pushnull(HSQUIRRELVM v)
Parameters: |
|
将一个null压入栈
sq_pushstring
void sq_pushstring(HSQUIRRELVM v, const SQChar * s, SQInteger len)
Parameters: |
|
Remarks: | 如果参数len小于0,VM将使用strlen(s)计算长度 |
在栈中压入一个字符串
sq_pushuserpointer
void sq_pushuserpointer(HSQUIRRELVM v, SQUserPointer p)
Parameters: |
|
将用户指针压入栈
sq_setbyhandle
SQRESULT sq_setbyhandle(HSQUIRRELVM v, SQInteger idx, HSQMEMBERHANDLE* handle)
Parameters: |
|
Returns: | SQRESULT |
从栈中弹出一个值,并使用成员句柄将其设置为类或实例成员(请参阅sq_getmemberhandle)
sq_setclassudsize
SQRESULT sq_setclassudsize(HSQUIRRELVM v, SQInteger idx, SQInteger udsize)
Parameters: |
|
Returns: | SQRESULT |
设置类的用户数据大小。 如果类”用户数据大小”大于0.当创建类的实例时,将在存储实例的内存块的末尾保留额外的空间。 实例的用户指针也将自动设置到此内存区域。 这允许最小化必须携带数据和类实例的应用程序中的分配。
sq_setclosureroot
SQRESULT sq_setclosureroot(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Returns: | SQRESULT |
从栈中弹出一个表,并将其设置为栈中位置idx处的闭包的根
sq_setinstanceup
SQRESULT sq_setinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer up)
Parameters: |
|
Returns: | SQRESULT |
将类实例的userpointer设置在栈中的位置idx。
sq_setnativeclosurename
SQRESULT sq_setnativeclosurename(HSQUIRRELVM v, SQInteger idx, const SQChar * name)
Parameters: |
|
Returns: | SQRESULT |
在栈中的位置idx处设置本机闭包的名称。 本机闭包的名称纯粹是为了调试pourposes。 当闭包在调用栈中时,通过函数sq_stackinfos()撤消该名称。
sq_setparamscheck
SQRESULT sq_setparamscheck(HSQUIRRELVM v, SQInteger nparamscheck, const SQChar * typemask)
Parameters: |
|
Remarks: | typemask包含一个零终止字符串,表示预期的参数类型。类型表示如下:’o’null,’i’integer,’f’flora,’n’integer or float,’s’string,’t’table,’a’array,’u’userdata,’ c’closure和nativeclosure,’g’generator,’p’userpointer,’v’thread,’x’instance(class instance),’y’class,’b’bool。和’.’任何类型。符号”|”可用作”或”以在同一参数上接受多个类型。可以使用的’或’数量没有任何限制。空格被忽略,因此可以在类型之间插入以提高可读性。例如,要检查将表视为’this’的函数作为第一个参数的字符串,将数字或userpointer作为第二个参数,该字符串将是”tsn | p”(table,string,number或userpointer)。如果参数mask包含的参数少于’nparamscheck’,则不会对其余参数进行类型检查。 |
设置栈顶部位置的本机闭包的参数验证方案。 允许验证函数接受的参数数量以及可选的类型。 如果函数调用不符合sq_setparamscheck设置的参数模式,则抛出异常。
//example
SQInteger testy(HSQUIRRELVM v)
{
SQUserPointer p;
const SQChar *s;
SQInteger i;
//no type checking, if the call comply to the mask
//surely the functions will succeed.
sq_getuserdata(v,1,&p,NULL);
sq_getstring(v,2,&s);
sq_getinteger(v,3,&i);
//… do something
return 0;
}
//the reg code
//….stuff
sq_newclosure(v,testy,0);
//expects exactly 3 parameters(userdata,string,number)
sq_setparamscheck(v,3,_SC(“usn”));
//….stuff
sq_setreleasehook
void sq_setreleasehook(HSQUIRRELVM v, SQInteger idx, SQRELEASEHOOK hook)
Parameters: |
|
Remarks: | 在删除用户数据内存之前,VM会调用函数挂钩。 |
在栈中的位置idx处设置userdata,类实例或类的release钩子。
/* tyedef SQInteger (*SQRELEASEHOOK)(SQUserPointer,SQInteger size); */
SQInteger my_release_hook(SQUserPointer p,SQInteger size)
{
/* do something here */
return 1;
}
sq_settypetag
SQRESULT sq_settypetag(HSQUIRRELVM v, SQInteger idx, SQUserPointer typetag)
Parameters: |
|
Returns: | SQRESULT |
在栈中的位置idx处设置对象的typetag(userdata或类)。
sq_tobool
void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool * b)
Parameters: |
|
Remarks: | 如果对象不是bool,则函数根据squirrel的规则将值转换为bool。 例如,数字1将导致true,数字0将导致false。 |
获取栈中位置idx的值为bool。
sq_tostring
void sq_tostring(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
将栈中位置idx处的对象转换为字符串,并将结果字符串压入栈中。
sq_typeof
SQObjectType sq_typeof(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
在栈中的位置idx处压入值的类型名称,它还为实现它的表和类实例调用_typeof元方法; 在这种情况下,压入的对象可能不是字符串(取决于_typeof实现)。
5、Calls
sq_call
SQRESULT sq_call(HSQUIRRELVM v, SQInteger params, SQBool retval, SQBool raiseerror)
Parameters: |
|
Returns: | SQRESULT |
Remarks: | 该函数弹出所有参数并将闭包留在栈中; 如果retval为true,则压入闭包的返回值。 如果通过sq_suspendvm()暂停执行该函数,则不会自动从栈中弹出闭包和参数。 |
调用闭包或原生闭包。
sq_getcallee
SQRESULT sq_getcallee(HSQUIRRELVM v)
Parameters: |
|
Returns: | SQRESULT |
在栈中压入当前运行的闭包。
sq_getlasterror
SQRESULT sq_getlasterror(HSQUIRRELVM v)
Parameters: |
|
Returns: | SQRESULT |
Remarks: | 压入的错误描述符可以是任何有效的松鼠类型。 |
将最后错误压入栈中。
sq_getlocal
const SQChar * sq_getlocal(HSQUIRRELVM v, SQUnsignedInteger level, SQUnsignedInteger nseq)
Parameters: |
|
Returns: | 如果变量存在于给定级别/ seq,则为局部变量的名称,否则为NULL。 |
返回栈中给定栈帧和索引的局部变量的名称,并压入当前值。 自由变量被sq_getlocal()视为局部变量,并且将在它们位于栈的基础之前返回,就在真正的局部变量之前。
sq_reseterror
void sq_reseterror(HSQUIRRELVM v)
Parameters: |
|
将虚拟机中的最后错误重置为null
sq_resume
SQRESULT sq_resume(HSQUIRRELVM v, SQBool retval, SQBool raiseerror)
Parameters: |
|
Returns: | SQRESULT |
Remarks: | 如果retval != 0,则压入生成器的返回值。 |
在栈的顶部位置恢复生成器。
sq_throwerror
SQRESULT sq_throwerror(HSQUIRRELVM v, const SQChar * err)
Parameters: |
|
Returns: | 返回由本机闭包返回的值,以便在虚拟机中引发异常。 |
设置虚拟机中的最后错误,并返回本机闭包必须返回的值,以便在虚拟机中触发异常。
sq_throwobject
SQRESULT sq_throwobject(HSQUIRRELVM v)
Parameters: |
|
Returns: | 由本机闭包返回的值,以便在虚拟机中引发异常。 |
从栈中弹出一个值将其设置为虚拟机中的最后错误。返回本机闭包必须返回的值,以便在虚拟机中触发异常(也称为SQ_ERROR)。
6、对象操作
sq_arrayappend
SQRESULT sq_arrayappend(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Returns: | SQRESULT |
Remarks: | 仅适用于数组。 |
从栈中弹出一个值,并将其压入到栈中位置idx的数组后面。
sq_arrayinsert
SQRESULT sq_arrayinsert(HSQUIRRELVM v, SQInteger idx, SQInteger destpos)
Parameters: |
|
Returns: | SQRESULT |
Remarks: | 仅适用于数组。 |
从栈中弹出一个值并将其插入指定位置的数组中
sq_arraypop
SQRESULT sq_arraypop(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Returns: | SQRESULT |
Remarks: | 仅适用于数组。 |
从栈中位置idx的数组后面弹出一个值。
sq_arrayremove
SQRESULT sq_arrayremove(HSQUIRRELVM v, SQInteger idx, SQInteger itemidx)
Parameters: |
|
Returns: | SQRESULT |
Remarks: | 仅适用于数组。 |
从数组中删除项目
sq_arrayresize
SQRESULT sq_arrayresize(HSQUIRRELVM v, SQInteger idx, SQInteger newsize)
Parameters: |
|
Returns: | SQRESULT |
Remarks: | 仅适用于arrays. newsize如果大于当前大小,则新数组槽将填充null值。 |
在栈中的位置idx处调整数组的大小。
sq_arrayreverse
SQRESULT sq_arrayreverse(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Returns: | SQRESULT |
Remarks: | 仅适用于数组。 |
将数组反转。
sq_clear
SQRESULT sq_clear(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Returns: | SQRESULT |
Remarks: | 仅适用于表和数组。 |
清除栈中位置idx处的表/数组的所有元素。
sq_clone
SQRESULT sq_clone(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Returns: | SQRESULT |
在位置idx处克隆表,数组或类实例,克隆它并在栈中压入新对象。
sq_createslot
SQRESULT sq_createslot(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Returns: | SQRESULT |
Remarks: | 在表委托中调用_newslot元方法。 它只适用于table。 [此函数自版本2.0.5以来使用sq_newslot()代替] |
从栈中弹出一个键和一个值,并对栈中位置idx的表或类执行set操作,如果插槽不存在则将创建它。
sq_deleteslot
SQRESULT sq_deleteslot(HSQUIRRELVM v, SQInteger idx, SQBool pushval)
Parameters: |
|
Returns: | a SQRESULT |
Remarks: | invoke the _delslot metamethod in the table delegate. it only works on tables. |
pops a key from the stack and delete the slot indexed by it from the table at position idx in the stack, if the slot does not exits nothing happens.
sq_get
SQRESULT sq_get(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Returns: | SQRESULT |
Remarks: | 这个调用将像普通的解引用一样调用委托系统,它只适用于表,数组和用户数据。 如果函数失败,则不会在栈中压入任何内容。 |
从栈中弹出一个键,并对栈中位置idx处的对象执行get操作,并将结果压入到栈中。
sq_getattributes
SQRESULT sq_getattributes(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Returns: | SQRESULT |
获取类mameber的属性。 该函数从栈中弹出一个键,并从栈中位置idx的类压入由它们键入的类成员的属性。 如果key为null,则函数获取类级别属性。
sq_getbase
SQRESULT sq_getbase(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Returns: | SQRESULT |
将存储在位置idx 的”class”的基类压入到栈中。
sq_getclass
SQRESULT sq_getclass(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Returns: | SQRESULT |
将存储位置idx中的”class instance”的类压入到栈中。
sq_getdelegate
SQRESULT sq_getdelegate(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Returns: | SQRESULT |
将栈中位置idx的对象的当前委托压入到栈中
sq_getfreevariable
const SQChar * sq_getfreevariable(HSQUIRRELVM v, SQInteger idx, SQInteger nval)
Parameters: |
|
Returns: | 纯松鼠闭包的自由变量的名称。如果出现错误或变量索引超出范围,则为NULL。 如果目标闭包是本机闭包,则返回名称始终为”@NATIVE”。 |
Remarks: | 该函数适用于松鼠闭包和本机闭包。 |
获取栈中位置idx处闭包的自由变量的值。
sq_getweakrefval
SQRESULT sq_getweakrefval(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Returns: | SQRESULT |
Remarks: | 如果函数失败,则不会在栈中压入任何内容。 |
在栈中的位置idx处所指向的对象压入弱引用。
sq_instanceof
SQBool sq_instanceof(HSQUIRRELVM v)
Parameters: |
|
Returns: | SQTrue,如果栈中位置-2处的实例是栈中位置-1处的类对象的实例。 |
Remarks: | 该函数不会从栈中弹出任何对象。 |
确定对象是否是某个类的实例。
sq_newmember
SQRESULT sq_newmember(HSQUIRRELVM v, SQInteger idx, SQBool bstatic)
Parameters: |
|
Returns: | SQRESULT |
Remarks: | 在类中调用_newmember元方法。 它只适用于类。 |
从栈中弹出一个键,一个值和一个对象(将被设置为成员的属性),并对栈中位置idx的类执行新的插槽操作,如果插槽不存在则将是创建。
sq_newslot
SQRESULT sq_newslot(HSQUIRRELVM v, SQInteger idx, SQBool bstatic)
Parameters: |
|
Returns: | SQRESULT |
Remarks: | 在table委托中调用_newslot元方法。 它只适用于table和class。 |
从栈中弹出一个键和一个值,并对栈中位置idx的表或类执行set操作,如果插槽不存在则将创建它。
sq_next
SQRESULT sq_next(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Returns: | SQRESULT |
向栈中压入数组,表或类槽的下一个键和值。 要开始迭代,此函数需要在栈顶部保留一个空值; 在每次调用时,函数将使用迭代器替换空值,并压入容器槽的键和值。每次迭代,应用程序都必须弹出前一个键和值,但保留迭代器(用作下一次迭代的参考点)。 迭代完所有插槽后,该函数将失败(请参阅表和数组操作)。
sq_rawdeleteslot
SQRESULT sq_rawdeleteslot(HSQUIRRELVM v, SQInteger idx, SQBool pushval)
Parameters: |
|
Returns: | SQRESULT |
从表中删除一个槽而不使用_delslot元方法。 从栈中弹出一个键,并从栈中位置idx的表中删除由它索引的槽,如果槽不存在则没有任何反应。
sq_rawget
SQRESULT sq_rawget(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Returns: | SQRESULT |
Remarks: | 仅适用于表和数组。 |
从栈中弹出一个键,并对栈中位置idx的对象执行get操作,而不使用委托或元方法。
sq_rawnewmember
SQRESULT sq_rawnewmember(HSQUIRRELVM v, SQInteger idx, SQBool bstatic)
Parameters: |
|
Returns: | SQRESULT |
Remarks: | 它只适用于类。 |
从栈中弹出一个键,一个值和一个对象(将被设置为成员的属性),并对栈中位置idx的类执行新的槽操作,如果槽不存在则将是创建。
sq_rawset
SQRESULT sq_rawset(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Returns: | SQRESULT |
Remarks: | 它只适用于表和数组。 如果函数失败,则不会在栈中压入任何内容。 |
从栈中弹出一个键和一个值,并对栈中位置idx的对象执行set操作,而不使用委托或元方法。
sq_set
SQRESULT sq_set(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Returns: | SQRESULT |
Remarks: | 此调用将像正常赋值一样调用委托系统,它仅适用于表,数组和用户数据。 |
从栈中弹出一个键和一个值,并对栈中位置idx处的对象执行set操作。
sq_setattributes
SQRESULT sq_setattributes(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Returns: | SQRESULT |
设置类mameber的属性。该函数从栈中弹出一个键和一个值,并在栈中位置idx的类上设置属性(由它们键入索引)。 如果key为null,则该函数设置类级别属性。 如果函数成功,则将旧属性值压入栈中。
sq_setdelegate
SQRESULT sq_setdelegate(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Returns: | SQRESULT |
Remarks: | 要从对象中删除委托,必须使用null作为委托而不是table。 |
从栈中弹出一个table,并将其设置为栈中位置idx处对象的委托。
sq_setfreevariable
SQRESULT sq_setfreevariable(HSQUIRRELVM v, SQInteger idx, SQInteger nval)
Parameters: |
|
Returns: | SQRESULT |
从栈中弹出一个值,并将其设置为栈中位置idx处的闭包的自由变量。
sq_weakref
void sq_weakref(HSQUIRRELVM v, SQInteger idx)
Parameters: |
|
Returns: | SQRESULT |
Remarks: | 如果idx位置的对象是一个integer,float,bool或null,则压入对象本身而不是弱ref。 |
将栈中位置idx处对象的弱引用压入栈。
7、字节序列化
sq_readclosure
SQRESULT sq_readclosure(HSQUIRRELVM v, SQREADFUNC readf, SQUserPointer up)
Parameters: |
|
Returns: | SQRESULT |
序列化(读取)一个闭包并将其压入到栈顶部,源是用户通过读回调定义的。
sq_writeclosure
SQRESULT sq_writeclosure(HSQUIRRELVM v, SQWRITEFUNC writef, SQUserPointer up)
Parameters: |
|
Returns: | a SQRESULT |
Remarks: | 带有自由变量的闭包无法序列化 |
序列化(write)栈顶部的闭包,目标是通过写回调用户定义的。
8、原始对象处理
sq_addref
void sq_addref(HSQUIRRELVM v, HSQOBJECT* po)
Parameters: |
|
添加对象句柄的引用。
sq_getobjtypetag
SQRESULT sq_getobjtypetag(HSQOBJECT* o, SQUserPointer* typetag)
Parameters: |
|
Returns: | SQRESULT |
Remarks: | 该函数也适用于实例。 如果目标对象是实例,则获取其基类的typetag。 |
获取原始对象引用的typetag(userdata或class)。
sq_getrefcount
SQUnsignedInteger sq_getrefcount(HSQUIRRELVM v, HSQOBJECT* po)
Parameters: |
|
返回给定对象的引用数。
sq_getstackobj
SQRESULT sq_getstackobj(HSQUIRRELVM v, SQInteger idx, HSQOBJECT* po)
Parameters: |
|
Returns: | SQRESULT |
从栈中获取一个对象并将其存储在对象句柄中。
sq_objtobool
SQBool sq_objtobool(HSQOBJECT* po)
Parameters: |
|
Remarks: | 如果对象非bool将始终返回false。 |
返回原始对象引用的bool值。
sq_objtofloat
SQFloat sq_objtofloat(HSQOBJECT* po)
Parameters: |
|
Remarks: | 如果对象是整数,则将其转换为float。 如果对象不是数字,则始终返回0。 |
返回原始对象引用的float值。
sq_objtointeger
SQInteger sq_objtointeger(HSQOBJECT* po)
Parameters: |
|
Remarks: | 如果对象是float,则将其转换为整数。 如果对象不是数字,则始终返回0。 |
返回原始对象引用的整数值。
sq_objtostring
const SQChar* sq_objtostring(HSQOBJECT* po)
Parameters: |
|
Remarks: | 如果对象未引用字符串,则返回NULL。 |
返回原始对象引用的字符串值。
sq_objtouserpointer
SQUserPointer sq_objtouserpointer(HSQOBJECT* po)
Parameters: |
|
Remarks: | 如果对象未引用用户指针,则返回NULL。 |
返回原始对象引用的userpointer值。
sq_pushobject
void sq_pushobject(HSQUIRRELVM v, HSQOBJECT obj)
Parameters: |
|
将对象句柄引用的对象压入栈。
sq_release
SQBool sq_release(HSQUIRRELVM v, HSQOBJECT* po)
Parameters: |
|
Returns: | SQTrue如果释放的对象句柄丢失了所有引用(使用sq_addref添加的引用)。否则SQFalse。 |
Remarks: | 当函数丢失所有引用时,该函数会将对象句柄重置为null。 |
从对象句柄中删除引用。
sq_resetobject
void sq_resetobject(HSQOBJECT* po)
Parameters: |
|
Remarks: | 必须使用此函数初始化每个对象句柄。 |
重置(初始化)对象句柄。
9、垃圾回收
sq_collectgarbage
SQInteger sq_collectgarbage(HSQUIRRELVM v)
Parameters: |
|
Remarks: | 这个api只适用于垃圾收集器构建(NO_GARBAGE_COLLECTOR没有定义) |
运行垃圾收集器并返回找到的(并删除)引用周期数
sq_resurrectunreachable
SQRESULT sq_resurrectunreachable(HSQUIRRELVM v)
Parameters: |
|
Remarks: | 这个api只适用于垃圾收集器构建(NO_GARBAGE_COLLECTOR没有定义) |
运行垃圾收集器并在栈中压入包含找到的所有无法访问的对象的数组。如果找不到无法访问的对象,则压入null。 此功能为在帮助调试引用周期。
10、调试接口
sq_getfunctioninfo
SQRESULT sq_getfunctioninfo(HSQUIRRELVM v, SQInteger level, SQFunctionInfo * fi)
Parameters: |
|
Returns: | SQRESULT. |
Remarks: | 返回的SQFunctionInfo结构的成员’funcid’是该函数的唯一标识符; 这对于在应用程序(例如分析器)中识别特定的松鼠代码片段非常有用。 如果栈中的闭包是本机C闭包,则此方法将失败。 |
typedef struct tagSQFunctionInfo {
SQUserPointer funcid; //unique idetifier for a function (all it’s closures will share the same funcid)
const SQChar *name; //function name
const SQChar *source; //function source file name
}SQFunctionInfo;
sq_setdebughook
void sq_setdebughook(HSQUIRRELVM v)
Parameters: |
|
Remarks: | 为了接收”每行”回调,必须使用行信息编译脚本。如果没有激活行信息,则只会调用’call / return’回调。 |
从栈弹出一个闭包,并将其设置为调试钩子。设置调试钩子时,它会覆盖任何以前设置的本机或非本机钩子。如果钩子为null,则将禁用调试钩子。
sq_setnativedebughook
void sq_setnativedebughook(HSQUIRRELVM v, SQDEBUGHOOK hook)
Parameters: |
|
Remarks: | 为了接收”每行”回调,必须使用行信息编译脚本。如果没有激活行信息,则只会调用’call / return’回调。 |
设置本机调试钩子。设置本机钩子时,它会覆盖任何以前设置的本机钩子或非本机钩子。 如果钩子为NULL,则将禁用调试钩子。
sq_stackinfos
SQRESULT sq_stackinfos(HSQUIRRELVM v, SQInteger level, SQStackInfos * si)
Parameters: |
|
Returns: | SQRESULT. |
获取调用栈中某个级别的调用栈信息。
暂无评论内容