# 01 语言基础 本章收录 TSL 语言基本构成、数据类型、变量/表达式、字符串与块环境语句等基础语法。 ## 目录 - [01 语言基础](#01-语言基础) - [目录](#目录) - [基础知识](#基础知识) - [TSL 程序的基本构成](#tsl-程序的基本构成) - [TSL 的符号](#tsl-的符号) - [保留字(关键字)](#保留字关键字) - [PROGRAM](#program) - [FOR](#for) - [REPEAT](#repeat) - [SYSTEM](#system) - [TO](#to) - [DO](#do) - [THEN](#then) - [BEGIN](#begin) - [WITH](#with) - [STEP](#step) - [ELSE](#else) - [REALPARAMCOUNT](#realparamcount) - [FUNCTION](#function) - [PARAMS](#params) - [IF](#if) - [END](#end) - [WHILE](#while) - [PARAMCOUNT](#paramcount) - [DOWNTO](#downto) - [SYSPARAMS](#sysparams) - [PROCEDURE](#procedure) - [Shl](#shl) - [DEBUGRETURN](#debugreturn) - [BREAK](#break) - [GOTO](#goto) - [Ror](#ror) - [NIL](#nil) - [OR](#or) - [CASE](#case) - [DebugRunEnvDo](#debugrunenvdo) - [LABEL](#label) - [DebugRunEnv](#debugrunenv) - [FALSE](#false) - [UNTIL](#until) - [RETURN](#return) - [EXIT](#exit) - [TRUE](#true) - [CONTINUE](#continue) - [AND](#and) - [ARRAY](#array) - [Shr](#shr) - [Rol](#rol) - [OVERLOAD](#overload) - [EXCEPTOBJECT](#exceptobject) - [LIKEEPS](#likeeps) - [CDECL](#cdecl) - [Sqlin](#sqlin) - [Not sqlin](#not-sqlin) - [LIKE](#like) - [Not Like](#not-like) - [IN](#in) - [Not IN](#not-in) - [SUDO](#sudo) - [RAISE](#raise) - [EXCEPT](#except) - [SETUID](#setuid) - [DIV](#div) - [LIKEEPSRATE](#likeepsrate) - [NOT](#not) - [FINALLY](#finally) - [MOD](#mod) - [PASCAL](#pascal) - [TRY](#try) - [FASTCALL](#fastcall) - [VAR](#var) - [ECHO](#echo) - [EXTERNAL](#external) - [THISFUNCTION](#thisfunction) - [STATIC 静态计算](#static-静态计算) - [SAFECALL](#safecall) - [NAN](#nan) - [INF](#inf) - [OUT](#out) - [STDCALL](#stdcall) - [CONST](#const) - [REGISTER](#register) - [GLOBAL](#global) - [_MYMEM_](#_mymem_) - [_MAXMEM_](#_maxmem_) - [MTIC](#mtic) - [MTOC](#mtoc) - [MTOC](#mtoc-1) - [MTOC(TICK:double)获得与某个指定的 TICK 之间的秒数](#mtoctickdouble获得与某个指定的-tick-之间的秒数) - [\_\_line\_\_](#__line__) - [\_\_stack\_frame](#__stack_frame) - [面向对象支持的保留字](#面向对象支持的保留字) - [TYPE](#type) - [CLASS](#class) - [FINDCLASS](#findclass) - [FINDFUNCTION](#findfunction) - [FACKCLASS](#fackclass) - [IS](#is) - [PROPERTY](#property) - [SELF](#self) - [VIRTUAL](#virtual) - [OVERRIDE](#override) - [PROTECTED](#protected) - [PUBLIC](#public) - [PRIVATE](#private) - [PUBLISHED](#published) - [STATIC](#static) - [远程调用客户端函数的保留字](#远程调用客户端函数的保留字) - [RDo2](#rdo2) - [RDo](#rdo) - [SQL 语法支持保留字](#sql-语法支持保留字) - [被系统保留未被使用的保留字](#被系统保留未被使用的保留字) - [标识符](#标识符) - [注释符](#注释符) - [编译选项与注释符](#编译选项与注释符) - [{$CompileOption}编译选项模式](#compileoption编译选项模式) - [条件编译](#条件编译) - [条件编译和 IF THEN 语句的差异](#条件编译和-if-then-语句的差异) - [预定义的条件编译标识](#预定义的条件编译标识) - [{$dependency class1,class2}依赖关系编译选项](#dependency-class1class2依赖关系编译选项) - [TSL 的数据类型](#tsl-的数据类型) - [Integer](#integer) - [Int64](#int64) - [Real](#real) - [实数的含义](#实数的含义) - [科学计数法](#科学计数法) - [Boolean](#boolean) - [TDateTime](#tdatetime) - [String](#string) - [字符串的表达](#字符串的表达) - [ANSI 字符串、Unicode 字符串与 UTF8 字符串](#ansi-字符串unicode-字符串与-utf8-字符串) - [字符串转义](#字符串转义) - [字符串的非转义表达%%](#字符串的非转义表达) - [字符串中#表达](#字符串中表达) - [Binary](#binary) - [Array,TableArray 数组类型](#arraytablearray-数组类型) - [一维数组的理解](#一维数组的理解) - [多维数组的理解](#多维数组的理解) - [字符串也可以作为数组的下标](#字符串也可以作为数组的下标) - [数组的表达方式](#数组的表达方式) - [Array of 类型注解(可选)](#array-of-类型注解可选) - [TSL 语言的数组和其他语言相比的特性](#tsl-语言的数组和其他语言相比的特性) - [TMatrix](#tmatrix) - [Matrix](#matrix) - [NIL](#nil-1) - [TGraph](#tgraph) - [TGraphGroup](#tgraphgroup) - [TExpression](#texpression) - [TFUNCTION](#tfunction) - [TCLASS](#tclass) - [ComObj](#comobj) - [COM 方法的调用例子](#com-方法的调用例子) - [TSLObj](#tslobj) - [常量与变量](#常量与变量) - [类型注解](#类型注解) - [全局变量](#全局变量) - [常量](#常量) - [常量及常量成员的定义与初始化](#常量及常量成员的定义与初始化) - [运行时常量的定义与初始化](#运行时常量的定义与初始化) - [常量与运行时常量的对比](#常量与运行时常量的对比) - [常量的产生对其它功能的扩展帮助](#常量的产生对其它功能的扩展帮助) - [GetEstSize](#getestsize) - [弱类型语言与变量类型运行时相关](#弱类型语言与变量类型运行时相关) - [TSL 语言变量的初始值](#tsl-语言变量的初始值) - [弱类型与强类型](#弱类型与强类型) - [数据类型转换与算符重载](#数据类型转换与算符重载) - [Explicit 变量声明的编译选项](#explicit-变量声明的编译选项) - [运算符](#运算符) - [赋值运算](#赋值运算) - [多参数赋值运算](#多参数赋值运算) - [算术运算符](#算术运算符) - [关系运算符](#关系运算符) - [逻辑运算符](#逻辑运算符) - [三目运算符](#三目运算符) - [?:判断求值三元运算符](#判断求值三元运算符) - [?:省略真表达式的三元运算符的特殊用法](#省略真表达式的三元运算符的特殊用法) - [支持矩阵的.?:表达式](#支持矩阵的表达式) - [位运算符](#位运算符) - [\[\]运算符](#运算符-1) - [表达式运算符](#表达式运算符) - [对象访问符](#对象访问符) - [矩阵运算符](#矩阵运算符) - [集合运算符](#集合运算符) - [过滤集运算符](#过滤集运算符) - [运算赋值运算符](#运算赋值运算符) - [With 设值运算符](#with-设值运算符) - [算符优先级](#算符优先级) - [?.模式](#模式) - [表达式](#表达式) - [算术表达式](#算术表达式) - [布尔表达式](#布尔表达式) - [逗号表达式](#逗号表达式) - [链式表达式](#链式表达式) - [标量链式算符](#标量链式算符) - [矩阵链式算符](#矩阵链式算符) - [字符串运算](#字符串运算) - [字符串的子串处理的算符支持](#字符串的子串处理的算符支持) - [字符串取指定位置的字符 StringValue\[Index\]](#字符串取指定位置的字符-stringvalueindex) - [字符串取子串 StringValue\[StartIndex:EndIndex\]](#字符串取子串-stringvaluestartindexendindex) - [字符串替换子串 StringValue\[StartIndex:EndIndex\]:=SubString](#字符串替换子串-stringvaluestartindexendindexsubstring) - [字符串删除子串 StringValue\[StartIndex:EndIndex\]:=""](#字符串删除子串-stringvaluestartindexendindex) - [字符串插入子串 StringValue\[Index:0\]:=SubString](#字符串插入子串-stringvalueindex0substring) - [字符串计算的算符支持](#字符串计算的算符支持) - [基础算符对字符串的支持](#基础算符对字符串的支持) - [+字符串相加](#字符串相加) - [字符串比较判断](#字符串比较判断) - [LIKE 字符串正则匹配判定](#like-字符串正则匹配判定) - [$处理字符串转换与拼装](#处理字符串转换与拼装) - [块环境设置语句](#块环境设置语句) - [块环境设置语句简介](#块环境设置语句简介) - [With \*,SysParamArray Do,与 With \*\*,SysParamArray Do](#with-sysparamarray-do与-with-sysparamarray-do) - [With =\> Do](#with-do) ## 基础知识 ### 大小写无关规则 **重要特性:TSL 语言是大小写无关(Case-Insensitive)的编程语言。** 这意味着: - **关键字**:`Begin`、`begin`、`BEGIN` 完全等价 - **函数名**:`Date()`、`date()`、`DATE()` 是同一个函数 - **变量名**:`myVar`、`myvar`、`MYVAR` 引用同一个变量 - **类型名**:`Integer`、`integer`、`INTEGER` 是相同的类型 **示例代码:** ```tsl function TestCaseInsensitive(): string begin var my_value := 100; my_value := my_value + 50; if my_value > 200 then return "large"; return "small"; end; ``` **注意事项:** - 字符串内容区分大小写:`'Hello'` 和 `'hello'` 不相同。 - 文件路径是否区分大小写取决于操作系统。 ### TSL 程序的基本构成 TSL 程序以函数定义体为基本结构,一个定义体内可包含多个函数。 ```tsl function FunctionName(param1, param2) begin statement; end; ``` 例子:显示当天日期。 ```tsl function HelloTsl(): string begin today := Date(); message := "Hello, today is " + DateToStr(today) + "!"; return message; end; ``` 简化写法: ```tsl function HelloTsl(): string begin return "Hello, today is " + DateToStr(Date()) + "!"; end; ``` ### TSL 的符号 #### 保留字(关键字) 保留字是指在 TSL 语言中具有特定的含义,是编写使用前必须了解的。目前 TSL 语言中的保留字一共有: ##### PROGRAM 程序开始的入口,一般用户不需要使用,在作为独立的 TSL 脚本时可以使用。 通常来说,倘若编写 TSL 代码作为 CGI 执行运行,系统默认以 PROGRAM 模式运行。虽然 TSL 可以省略 PROGRAM 关键字,但是使用 PROGRAM 关键字可以使得 TSL 代码里包含子函数。 例如: ```tsl program Test; function sub1(); begin Writeln('Execute Sub1'); end; begin Sub1(); end. ``` ##### FOR 循环子句,可组成 FOR TO DO 或者 FOR DOWNTO DO 循环子句。 参见:TO,DOWNTO ##### REPEAT 循环子句,可组成 REPEAT 循环子句。 ##### SYSTEM 系统函数前缀,因为系统函数可能被用户函数重载,如果要指定调用系统函数,可以用 system.funcname 的模式。例如 system.close()是指定调用系统的收盘价函数。 参见:用户和函数相关函数 ##### TO 循环子句往后,可组成 FOR TO DO 循环子句,也可以用于 CASE 和 SELECT 语句中。 参见:FOR,DOWNTO ##### DO 循环子句做,可组成 FOR TO/DOWNTO DO 或者 WHILE DO 循环子句。此外,DO 还可以组成 WITH DO 设置语句的运行时环境。 参见:WHILE,FOR,WITH ##### THEN 条件子句那么,可组成 IF THEN 或者 IF THEN ELSE 条件子句,详细见 IF ##### BEGIN 语句段开始,与 END 组合成 BEGIN END 语句段,详细见 END ##### WITH 为语句设置运行时环境,可组成 WITH DO,在类 SQL 语法中,可在 JOIN 子句中使用 with(expLeft…,expRight)作为快速条件。 参见:DO,With 设值运算符,块环境设置语句,WITH ON 条件。 ##### STEP for 循环语句里的步长,for 的缺省步长为 1。 参见:FOR,TO,DOWNTO ##### ELSE 条件子句否则,可组成 IF THEN ELSE, 参见:IF,THEN ##### REALPARAMCOUNT 系统内置变量,用来得到函数调用时实际被送入的参数个数。用于下标方式获取参数。 例如: ```tsl a := function(i1, i2) begin echo '实际送入的参数:', realparamcount; echo '参数:', paramcount; return 1; end; return Call(a, 1); ``` 结果:返回 1。 参见:PARAMS ##### FUNCTION 函数声明开始,组成类似于 `function Xxx(): ... begin ... end;` 的函数块。 ##### PARAMS 系统内置变量,按序列访问函数参数。`Params[1]` 表示第一个参数,`Params[n]` 表示第 n 个参数;参数个数可用 `ParamCount` 获取。通常优先使用参数名称,仅在不定参数个数的场景使用 `Params`。 参见:PARAMCOUNT ##### IF 条件子句如果,可组成 IF THEN 或者 IF THEN ELSE 条件子句,详细见 THEN ##### END 语句段结束,与 `begin/end` 组合成语句块。 ##### WHILE 循环子句,可组成 `while ... do` 循环语句。 参见:TO ##### PARAMCOUNT 系统内置变量,用来得到函数的参数个数。用于下标方式获取参数。 参见:PARAMS ##### DOWNTO 循环子句往前,可组成 FOR DOWNTO DO 循环子句, 参见:FOR,TO ##### SYSPARAMS 用语系统环境变量存贮的数组。 除了特殊的环境变量以外,直接访问 SysParams 的下标利用 SetSysParam 和 GetSysParam 的功能相同。 ```tsl SysParams["MM"] := 1;等同于 SetSysParam("MM", 1); ``` 直接使用 SysParams 来访问和设置系统环境的值的性能会优越于 SetSysParam 和 GetSysParam 函数,尤其当某系统环境变量的值是一个数组的时候。 参见:系统参数设置和获取函数 ##### PROCEDURE 与 FUNCTION 类似,但是在函数头后不允许加返回类型值。 ##### Shl 左移位运算符,X Shl Y,二进制 X 左移 Y 位 范例: ```tsl return 6 shl 3; // 结果:48 // 返回十进制 (6=110) 左移3位后得到二进制110000,十进制是48 ``` ##### DEBUGRETURN 调试返回,后面跟返回值,可在任何地方直接将结果返回到客户端,而不是象 RETURN 一样返回到上一级别。 ##### BREAK 终止循环语句段,可用于 FOR 或者 WHILE 循环中, 参见:循环语句,FOR,WHILE ##### GOTO 无条件跳转语句,需要 LABEL 配合,参见 GOTO ##### Ror 循环右移位运算符,X Ror Y,二进制 X 循环右移 Y 位, 原来的低 Y 位变成高 Y 位 范例: ```tsl return 18 Ror 1; // 结果9 // 返回十进制 (18=10010) 右移1位后得到二进制1001,十进制是9 ``` ##### NIL 数据类型为 NIL 的常量 ##### OR ##### CASE 多分支条件语句,CASE OF ##### DebugRunEnvDo ##### LABEL 无条件跳转的标号定义语句,参见 GOTO ##### DebugRunEnv ##### FALSE ##### UNTIL 循环子句 REPEAT 的结束判断符。 ##### RETURN 函数返回,后面可跟返回值 ##### EXIT ##### TRUE ##### CONTINUE 循环语句段中继续,可用于 FOR 或者 WHILE 循环中, 参见:循环语句,FOR,WHILE ##### AND ##### ARRAY 数组类型初始化,方法为:Array(下标 0:取值 0,下标 1:取值 1,…,下标 N:取值 N),当下标省略的时候,默认下标从整数 0 开始,例如 Array(1,2,3,4)相当于 Array(0:1,1:2,2:3,3:4),数组下标支持字符串,例如 Array('a':1, 'b':2),多维数组的声明例子:Array(('a':1,'b':2),('a':2,'b':3)),其规则为取值为数组,在 ARRAY 声明中的数组取值不再需要 ARRAY 关键字。注意:如果即无下标也无取值,则为空数组,例如 Array(),数组类型 参见:Array,TableArray 数组类型 ##### Shr 右移位运算符,X Shr Y,二进制 X 右移 Y 位 范例: ```tsl return 18 shr 3; // 结果2 // 返回十进制 (18=10010) 右移3位后得到二进制10,十进制是2 ``` ##### Rol 循环左移位运算符,X Rol Y,二进制 X 各位左移 Y 位,原来的高 Y 位变成低 Y 位 范例: ```tsl return 6 rol 3; // 结果:48 // 返回十进制 (6=110) 左移3位后得到二进制110000,十进制是48 ``` ##### OVERLOAD ##### EXCEPTOBJECT 获得异常对象实例,异常对象包含 ErrNo,ErrLine,ErrInfo 三个属性。参见错误控制,以及调试语句 ##### LIKEEPS LIKE 的精度设置,可以用 `:=` 进行设置,也可以获得其值,默认值为 1e-6。 参见:LIKE,LIKEEPSRATE ##### CDECL ##### Sqlin 行记录的存在于判断。 语法:v SQLIn R 其中,v 一定是 R 的一条记录才是真。以一条记录为判定单位。 范例一: ```tsl v := array(1, 2); r := array((1, 2), (2, 3)); return v sqlin r; // 返回结果为1 ``` 范例二: ```tsl v := array(1, 3); r := array((1, 2), (2, 3)); return v sqlin r; // 返回结果为0 ``` 范例三:与 In 的区别。 ```tsl a := array(); a["1 ifin array(1,2)"]['In'] := 1 in array(1, 2); a["1 ifin array(1,2)"]['sqlin'] := 1 sqlin array(1, 2); a["1 ifin array((1,2))"]['In'] := 1 in array((1, 2)); a["1 ifin array((1,2))"]['sqlin'] := 1 sqlin array((1, 2)); a["array(1,2) ifin array((1,2),(2,3))"]['In'] := array(1, 2) in array((1, 2), (2, 3)); a["array(1,2) ifin array((1,2),(2,3))"]['sqlin'] := array(1, 2) sqlin array((1, 2), (2, 3)); a["array(1,3) ifin array((1,2),(2,3))"]['In'] := array(1, 3) in array((1, 2), (2, 3)); a["array(1,3) ifin array((1,2),(2,3))"]['sqlin'] := array(1, 3) sqlin array((1, 2), (2, 3)); return a; // 返回: ``` ###### Not sqlin Not sqlin 是与 Sqlin 相对应的操作符,两者语法结构相似但逻辑功能完全相反。 功能:以行的模式来判定是否不存在于数组中。 语法:v Not SQLIn R 其中,v 一定不是 R 的一条记录才是真。以一条记录为判定单位。 示例: ```tsl v := array(1, 2); r := array((1, 2), (2, 3)); return v not sqlin r; // 返回结果为0 v := array(1, 3); r := array((1, 2), (2, 3)); return v not sqlin r; // 返回结果为1 ``` ##### LIKE 字符串模式匹配判定符,判定是否匹配于指定的正则表达式。 例如: '2009-1-1' like "\\d+-\\d+-\\d+" 返回为真 实数 LIKE,例如 1.000001 like 1 为真,实数相等一般要避免用等于(=)来判断 Like 的计算方法如下: 如果两个数的差的绝对值[,…],输出的内容必需是简单类型,否则仅仅只是输出一个基本的类型信息。 ```tsl echo "Today is ", DateToStr(Today()), "now->", TimeToStr(Now()); ``` 如果在平台运行,会输出信息到客户端 固定功能用法: Echo #127 可清除掉客户端 ECHO 窗口中的内容。 范例: 范例一: ```tsl // 打印当前时间 echo "现在时间:", DateTimeToStr(Now()); ``` 范例二: ```tsl // 清除打印窗口的信息,清除命令会在30s后执行 echo "待清除信息"; Sleep(30000); echo #127; ``` ##### EXTERNAL 说明函数是外部函数,来自于其他的动态库。 ##### THISFUNCTION THISFUNCTION 返回一个函数类型 THISFUNCTION 可得到当前运行的函数 THISFUNCTION(FuncName)可以得到指定 FuncName 的函数 THISFUNCTION(Object.FuncName)可以得到指定对象的方法。 THISFUNCTION(CLASS(ClassName).FUNCNAME)可以得到指定类的类方法。 参考:表达式相关函数 ##### STATIC 静态计算 语法:STATIC Expression [name nameExpression] 功能:指定后边的表达式为静态计算(常量计算),该计算只计算一次,用于加速。 其中, Expression :为表达式 nameExpression:为该静态计算标识符,每个标识符代表的表达式只执行一次,即若该标识符在第二次被调用时,则直接返回第一次执行的结果。 例 1: ```tsl begin return Teststatic("BBBB"); end; function teststatic(key); begin // 这个变量A的值是一个不需要每次调用重新构造的静态计算,即它右边的表达式不管上层调用多少次,它只执行一次 A := static array("ABCD":1, "BBBB":2, "CCCC":3……..); return A[key]; end; ``` 例 2: ```tsl begin return staticstockname("SZ000002"); end; function staticstockname(key); begin return static StockName(key) name"stkname"$key; // 每个股票代码求名称都只要计算一次,假如StockName函数耗费的时间比较长,则静态计算可以加速。 end; ``` ##### SAFECALL ##### NAN NOT A NUMBER,非数字,例如 0.0/0.0 的结果就是 NAN ##### INF 无穷大,例如 1/0.0 的结果就是 INF ##### OUT 在调用函数的时候,在参数之前标识,与 VAR 一样,标明是可修改参数。除非系统使用 VarByRef 编译选项,否则默认为可修改参数。 ##### STDCALL ##### CONST 功能一:与 OUT 相反,标明是不可修改参数。 功能二:定义常量的关键字。 ##### REGISTER ##### GLOBAL 指定后边的变量类型为全局变量,全局变量可以在不同的函数中访问到。 例: ```tsl begin global x, y; x := 100; testglobal(); end; function testglobal(); begin global x; echo x; end; // 使用了全局变量之后,以上的 testglobal 函数会打印出 100。 ``` ##### _MYMEM_ 应用已经使用的内存大小。 ##### _MAXMEM_ 应用允许使用的最大内存大小。 ##### MTIC 高精度计算时间,得到 CPU 运行过的计数周期,并设置默认的开始计时,一般会利用 MTOC 来计算耗费的时间。 ```tsl MTIC; A := 0; for i := 0 to 99999 do A++; return MTOC; ``` 以上代码可以计算所耗费的秒数 ##### MTOC 高精度计算时间,得到和上一次调用 MTIC 到当前所耗费的时间,为一个浮点秒数,也可以带参数指定计算的开始点,一般开始点由 MTIC 获得。 ###### MTOC 获得与上一次调用 MTIC 之间的秒数。 ```tsl MTIC; A := 0; for i := 0 to 99999 do A++; return MTOC; ``` 以上代码可以计算 mtic 和 mtoc 之间的代码执行所耗费的秒数。 ###### MTOC(TICK:double)获得与某个指定的 TICK 之间的秒数 默认 MTOC 和上次 MTIC 匹配,但是也可以指定某个 MTIC 的返回来计算时间 ```tsl T1 := MTIC; for i := 0 to 9999 do A++; TE1 := MTOC(T1); MTIC; for j := 0 to 9999 do A++; TE2 := MTOC(T1); return array(TE1, TE2, MTOC); ``` ##### \_\_line\_\_ 关键字,获得当前的行号。 例如:`echo __line__;` ##### \_\_stack_frame 说明:获得调用的堆栈的函数名以及行号 返回结构解析 ##### 面向对象支持的保留字 关于各个关键字的详细内容见面向对象 TSL 章节 参见:Object TSL ###### TYPE 用来定义类: ```tsl type abcd = class ``` Public ```tsl V:Integer; function return V(); begin return V; end; end; ``` ###### CLASS 类关键字,用来定义类,见 TYPE。 也可以返回指定的类,如 class(abcd) 也可以用来得到强制类型的对象,例如 class(abcd,aObject),返回强制对象 aObject 为 abcd 类。 ###### FINDCLASS 查找类,与 CLASS 用法类似。 返回指定名称的类:FindClass("abcd") 得到强制类型的对象:FindClass("abcd",aObject),返回强制对象 aObject 为 abcd 类。 与 CLASS 关键字不同,当不存在指定的类的时候,或者不是指定对象的父类时,并不抛出异常,而是返回一个整数 0。 ###### FINDFUNCTION 查找函数,与 FINDCLASS 用法类似。 返回指定名称的函数:FindFunction("Function1")。 返回指定对象的类方法:FindFunction("Method1",aObject),返回对象 aObject 的 Method1 方法。 返回指定单元对象:findfunction(UnitName),返回单元对象 UnitName。 当找不到指定的函数,并不抛出异常,而是返回一个整数 0。 ###### FACKCLASS 虚假类,仅仅用来做类描述。 ###### IS 判断符,判断对象是否是指定类的实例。 语法:Object Is Class 返回:真假。 ####### Not IS not is 用于判断是否不是指定对象的实例。若不是指定对象的实例,则返回 True;否则返回 False。 与 FAQ:IS 语法结构相似但逻辑功能完全相反。 示例: ```tsl a := 1; ret := a not is class(TStringList); return ret; // 返回结果:1 a := new TStringList(); ret := a not is class(TStringList); return ret; // 返回结果:0 ``` ###### PROPERTY 定义对象的属性,详细内容见面向对象 TSL。 ```tsl property A[:String] read GETA write SETA; property A[:String] Index 1 read GETA Write SETA; ``` ###### SELF SELF 得到当前的对象。 ###### VIRTUAL 虚方法关键字,指定的函数可被重写。 ###### OVERRIDE ###### PROTECTED 可视域为受保护的,只有自己当前类和继承类可以访问。 ###### PUBLIC 可视域为公共的,大家都可以访问 ###### PRIVATE 可视域为私有的,只有自己当前类可以访问。 ###### PUBLISHED 可视域为发布,与 PUBLIC 可视域相同 ###### STATIC 指定后边的成员变量类型为静态,静态成员变量是所有的实例共享的全局的,当一个类需要使用到公共变量的时候可以采用静态成员变量。 ##### 远程调用客户端函数的保留字 ###### RDo2 注: Rdo2 在客户机运行的时候,需要用户在权限上许可,具体可参考:平台模型远程调用客户端函数,访问客户端的资源 范例 ```tsl if Rdo2 InputQuery("nput", "Hint", Value) then return Value else return "Canceled"; ``` 可以在本机弹出一个输入的对话框,并返回输入的串,如果取消则返回“Canceled” ###### RDo ##### SQL 语法支持保留字 | 相关的关键字 | 含义 | | --- | --- | | Select | 查询语句,指定由查询返回的列。详细使用方法见SELECT查询 | | VSelect | 查询语句,返回一个值 | | SSelect | 查询语句,返回一维数组 | | MSelect | 查询语句,返回Matrix类型数组 | | Distinct | 取唯一值,去重复项 | | SelectOpt | 返回指定类型值,selectopt(type),type值不同,返回不同类型的值。详见select字句语法。 | | DRange | Drange(N to M): 从查询结果集中输出从N到M之间的行;
Drange(N of M): 从查询结果集中输出从 (N-1)/M * 记录总条数到 N/M * 记录总条数 -1 之间的行; | | As | 对列命名 | | From | 数据的来源表 | | MarketTable | 高频行情数据表 | | InfoTable | 财务类数据表关键字 | | TradeTable | 交易明细数据表 | | SqlTable | 用于与第三方数据库交互的关键字 | | HugeSqlTable | | | KeepNull | | | Datekey | 取行情数据时,指定日期关键字 | | Of | 取数据时,指定股票关键字 | | Order | 排序,与by同时使用:order by | | By | 排序,与order同时使用:order by | | Where | 条件 | | Desc | 排序,逆序 | | Asc | 排序,正序 | | Group | 分组 | | Having | 聚集 | | ChecksumOf | 生成哈希索引 | | Countof | 记录统计 | | SumOf | 和 | | MaxOf | 最大值 | | StdevOf | 标准差 | | VarOf | 在险价值 | | TotalVarOf | | | NormOf | 平方和的平方根 | | MedianOf | 中值 | | AveDevOf | 离散度 | | GeoMeanOf | 几何平均值 | | SkewOf | 偏度 | | KurtosisOf | 峰度 | | Skew2Of | 偏度 | | Kurtosis2Of | 峰度 | | LargeOf | 最大值 | | PercentileOf | 百分点 | | QuartileOf | 四分位的值 | | TrimMeanOf | 返回数据集中的内部平均值,从头尾去掉指定百分比的数据点,再求平均值 | | CountOf | 记录个数 | | AvgOf | 平均值 | | MinOf | 最小值 | | AggOf | 利用回调函数计算聚集的值 | | StdevpOf | 统计标准偏差 | | VarpOf | 统计方差 | | ModeOf | 众数 | | DevSqOf | 样本平均值偏差的平方和 | | HarMeanOf | 调和平均值 | | Checksum_AggOf | 校验和 | | SmallOf | 最小值 | | PercentRankOf | 数据集中X排位的百分点的值 | | Rankof | 排位 | | FrequencyOf | 数值区间在数据集中出现的频率 | | ProductOf | | | RefOf | 往前取数据 | | RefsOf | | | AggValue | 当前参与聚集的列的值 | | ThisGroup | 指定分组 | | ThisRow | 当前行的数据值 | | ThisRowIndex | 当前行的相对索引值 | | ThisOrder | 当前排序 | | Insert | 插入数据 | | InsertFields | 插入数据的字段列表 | | Values | 设置或者取得Name=Value模式串中指定的Name的Value值 | | Update | 修改数据 | | Set | 修改数据 | | Delete | 删除数据 | | DeleteOpt | 设定删除数组时是否自动修改下标,SelectOpt对稀疏矩阵用的时候很有意义 | | FetchFirst | 查询第一条记录 | | FetchNext | 查询下一条记录 | ##### 被系统保留未被使用的保留字 EXPORTS DISPINTERFACE LIBRARY ASM RECORD RESOURCESTRING THREADVAR CONSTRUCTOR DESTRUCTOR INLINE PACKED ABSTRACT INHERITED #### 标识符 标识符的定义:标识符就是以字母开头的字母数字序列,大小写不敏感。可以用来标示常量、变量、程序、函数等。 例如 TSL 程序的基本构成示例中的 HelloTSL,dToday(变量名)、strToday(变量名)都是标识符。 标识符的命名规则: 1)选用的标识符不能和保留字相同。 2)在定义标识符时可以用的字符: A—Z;a—z;0—9; #### 注释符 注释符是什么呢?注释符注释的部分是仅仅给程序员注释所用,对于运行而言是毫无意义的,只是为了阅读程序理解更方便。 TSL 语言支持四种主要的注释符: - `//`:行注释,直到行尾。 - `#!`:为 CGI 场景保留,语义与 `//` 相同。 - `{ ... }`:块注释。 - `(* ... *)`:块注释,可用于与 `{ ... }` 交替实现嵌套。 嵌套注释示例: ```tsl value := 0; { value := value + 1; (* 小段注释 *) value := value * value; } ``` #### 编译选项与注释符 在 TSL 语言中,为了改变编译的行为,会有一些编译选项,而编译选项也是利用注释符来实现的。 TSL 语言的编译选项和 PASCAL 语言类似,目前支持下列几种用法: ##### {$CompileOption}编译选项模式 例如{$VarByRef-}可以改变函数调用的入口参数为形参,而{$Explicit+}则可以使得变量使用前必需申明,{$GridCompute-}可以关闭掉#的网格操作符。这些内容将在后续相关章节中详细提到。 在 C 语言中,采用#CompileOption 的形式作为编译选项,大部分语言都支持编译选项以改变编译的默认行为。 参考:VarByRef 编译选项,Explicit 编译选项 ##### 条件编译 TSL 语言使用{$DEFINE} {$IFDEF}{$IFNDEF} {$ELSE} {$ENDIF} {$UNDEF}进行条件编译。 {$DEFINE Identifier} 定义标识 {$UNDEF Identifier} 取消定义标识 {$IFDEF Identifier} 判定是否定义了标识 {$IFNDEF Identifier} 判定是否未定义标识 {$ELSE} 在{$IFDEF}以及{$IFNDEF}条件编译中作为否定条件进入语句 {$ENDIF} {$IFDEF}或者{$IFNDEF}条件编译的结束 例如: ```tsl {$DEFINE SampleID} // 定义一个名为SampleID的编译标识 {$IFDEF SampleID} // 判定是否定义了SampleID echo "Defined SampleID"; {$else} // 否则(如果未定义) echo "1 Undefined SampleID"; {$ENDIF} // IFDEF的结束 {$UNDEF SampleID} // 此处将SampleID的定义取消 {$IFDEF SampleID} Error codesdjk sdcnkjsdnksd//此处是错误代码,由于在条件编译中,未定义SampleID,所以此块不会被编译,不会出错 {$else} //否则(如果未定义) echo "2 Undefined SampleID"; {$ENDIF} ``` 运行打印结果为: Defined SampleID 2 Undefined SampleID ##### 文件包含 支持通过 `{$I}` / `{$INCLUDE}` 将外部文件内容插入当前编译单元。 示例: ```tsl {$I "common.tsl"} ``` ###### 条件编译和 IF THEN 语句的差异 条件编译是仅仅编译符合条件的内容,而不像 IF 需要运行时判断,效率更高。 条件编译中的不需要编译的代码即便是有错误代码块也可以编译成功,这样可以很简单用条件编译的模式处理那些未完成代码。(比使用注释好,采用注释存在注释嵌套问题) ###### 预定义的条件编译标识 tslnewtechcache 如果定义了该标识,表明技术指标相关函数支持缓存定义 tslver31 如果定义了该标识,表明当前支持版本 3.1 的语法 nilinvoke 如果定义了该标识,表明当前支持 calcctrlword 功能 cov 如果定义了该标识,表明当前支持双序列聚集和时间序列函数 commaexpr 如果定义了该标识,表明当前支持逗号表达式 weakptr 如果定义了该标识,表明支持弱引用 AutoWeak 如果定义了该标识,表明支持自动弱引用 例如: ```tsl {$IFDEF commaexpr} //判定是否定义了commaexpr Echo (a := 1, a += 100, a); {$else} //否则(如果未定义) echo "不支持逗号表达式"; {$ENDIF} //IFDEF的结束 ``` 若当前环境支持逗号表达式,则打印结果为:101 否则打印结果为:不支持逗号表达式 ##### {$dependency class1,class2}依赖关系编译选项 一个类如果依赖另上一个类,在类的定义里的第一行可以用该编译选项加入依赖关系。 语法:{$dependency class1,class2} 目前,该依赖关系仅在 TSL 的编辑器中用于自动完成中。用来决定当前开发中的函数自动完成的标识符和函数需要引入哪些其它的类。 例如,在编辑一个函数时,给函数的参数中输入一个实例对象变量,由于天软中变量都是弱类型,无法通过该变量快速查找到目标类的相关方法等信息。 此时,可通过在函数中增加{$dependency class1,class2}语句,对指定类的信息进行加载,使得在编辑函数时,能够通过不完整的函数名自动搜索到相关模型,并补充完整。 具体表现如: ### TSL 的数据类型 数据是程序设计的一个重要内容,一般的高级程序语言都提供了种类繁多的数据类型,用来完成不同特色的程序设计。数据类型复杂,往往会使初学者不容易全面和深入掌握。 TSL 语言的数据类型从简洁和实用性考虑,目前提供的数据类型分为:简单类型、扩展类型,其中简单类型分为整型、实型、布尔型、字符串型和日期型,二进制流类型,扩展类型分为数组型、NIL 型、TGraph 型、TGraphGroup 型和表达式型。 #### Integer 整数型,一个整型数据用来存放整数,TSL 语言中的整型数据是一个带符号的 32 位数据,其可以表达的数值范围是-2147483648..2147483647。 整数的基础含义每个读者都明白,和实数类似的,在 TSL 中,用户一般也无需理解整数的具体表达方式,直接使用就可以了。 但是和实数一样,当处理字节流或者和 DLL 发生关系的时候,整数在计算机中的具体表示就显得重要了。 其他计算机里的整数类型: Byte,ShortInt:字节,短整,顾名思义,存贮为 8 位,占用一个字节。可表达的范围为:有符号为-128 ~ 127,无符号为 0 ~ 255。所谓有符号或者无符号是指出是否需要可以表达负数。 Word,SmallInt:字,小整,存贮为 16 位,占用两个字节。可表达的范围为:有符号-32768 ~ 32767,无符号 0 ~ 65535。 Dword,LongInt:双子,长整,存贮为 32 位,占用四个字节。可表达的范围为:有符号-2147483648 ~ 2147483647,无符号 0 ~ 4294967295。所谓 2G,4G 就是指的有符号或者无符号下 32 位最大的表达大小。 Int64:64 位整数,存贮为 64 位,占用 8 个字节,可表达范围为:-2^63 ~ 2^63-1。 TSL 里默认采用的整数是有符号的 LongInt,但是提到整数运算,不得不提到关于绝大多数语言里的整数溢出问题。例如,在 C 语言中,如果整数运算越界了,例如无符号的 4294967295+1,结果为 0。在 TSL 语言中,为了应用开发的简便性,当溢出的时候,数据会自动转为浮点数来处理,变为浮点的 4294967296。所以一般情况下,用户可以不用理会数据运算溢出问题。当然特殊情况下例外,假如用户需要将运算结果存贮到数据库或者文件字节流中,由于运算溢出了,而原来设计存贮的数据类型不足以表达,依旧会产生问题。 TSL 语言的整数常量支持如下四种表达方法: 直接由数字表达十进制,如 100 表示十进制 100。 由数字 E 密表达十进制,如 1E2 表示十进制 100。 由 0x 开头表示十六进制,如 0x100 表示十进制的 256。 由 0b 开头表示二进制,如 0b100 表示十进制的 4。 由 0o 开头表示八进制,如 0o100 表示十进制的 64。 #### Int64 64 位整数,当 Integer 常量超过 32 位表达的时候,会自动采用 64 位整数,除此以外,也可以采用在整数常量末尾加上 L 来表示 64 位整数,例如 100L 表示值为 100 的 64 位整数。 #### Real 实数型,一个实型数据用来存放实数,TSL 语言中的实型数据是一个带符号的 64 位数据,其可以表达的数值范围是 5.0e-324..1.7e308,有效位数是 15..16。由于 TSL 的类型无需要申明,因此实数常量的书写方法必须带有小数点,例如:0 表示整数 0,而 0.00 则表示实数 0。 TSL 语言的实数常量除了直接使用数字加小数点外,还可以用例如 1.10E10 这种科学记数法。 此外,当一个未含有小数点的 10 进制整数表达方式超过了 32 位整数所表达的范围,TSL 语言将自动将其当做实数常量。 ##### 实数的含义 实数的基础含义每个读者都应明白,为了用户使用方便,在 TSL 中用户一般不需要去理解关于实数更多的知识,只需要使用就可以了。 但有例外,一个是将实数处理成为要存贮的字节流,写入文件或者和其他的外部程序发生交互的时候,需要理解实数在计算机中的具体存贮大小。二是和外部 DLL(Dynamic Link Library,一种在 Windows 中经常使用并依赖的开发技术,使得开发可以模块式开发)发生关系的,必需明确实数的计算机里的标准类型。 在计算机里,实数一般是以浮点的方式来表达的,关于浮点的表达方式在这里就不做具体描述。我们只关注下具体的数据类型,一般存在如下数据类型: Single 也叫 Float:单精度浮点数,存贮位数为 32 位,也就是占用四个字节的存贮空间,可表达的范围为:负数为-3.4E38 ~ -1.4E-45,正数为 1.4E-45 ~ 3.4E38,有效精度为十进制的 7 位。目前,由于浮点协处理已经成为计算机的标准配置,计算机内存以及硬盘以及变得很大,这种损失精度的类型已经很少使用了,主要应用在那种对存贮空间很苛刻,对于精度要求不大的应用中。 Double:双精度浮点数,存贮位数位 64 位,也就是占用八个字节的存贮空间,可表达的范围为:正数为 5.0E-308 ~ 1.7E+308,负数为-1.7E+308~-5.0E-308,有效精度为十进制的 16 位。Double 是目前应用得最广的数据类型,也是 TSL 语言中默认采用的实数数据类型。当和 DLL 发生关系的时候,又或者执行字节流处理的,TSL 会自动按照指定的位数或者类型采用 DOUBLE 或者 Single 类型。 其他实数数据类型:有占用 16 个字节的 Long Double 类型,有占用 10 个字节的 Extended Double 类型,这些类型可以描述更精确地数字,可以表达更大的数据范围,但是这些类型并不常用。 特殊的实数 在实数中,有几个特殊的实数,-INF,+INF,NaN。也就是负无穷大,正无穷大,以及错误的数据(Not a Number)。 这些为什么放在实数中呢?事实上这些数据往往都是实数运算产生的结果,例如正数处以 0 得到的是+INF,负数处以 0 得到的是-INF,而 0 处以 0 则是 NaN。 TSL 语言提供了一些方法给用户去判断是否是这些特殊的实数。 ##### 科学计数法 支持科学计数法 a\*10^n 可以用 aEn 来表达。 例如 123 可以写为 1.23e2,0.01234 可以写成 1.234e-2。 #### Boolean 在计算机中,Boolean 类型事实上是被使用得最多的类型,只是很多是隐式使用。例如所有的逻辑判断的结果都是一个 Boolean 类型,而计算机程序中到处都充斥着逻辑判断。 TSL 的 Boolean 型的内部存贮其实只是一个整数,1 为真,0 为假。但是与 C 语言类型类似,对于数字,非 0 为真,0 为假。此外,NIL 类型也被判断为假。 其他语言中,按照布尔类型占用的大小,有 LongBool 和 ByteBool 之分,其实,要表达一个布尔类型,一个位就足够了,这也叫 BitBool,事实上,在汇编语言中,经常判断某个指定位是否为 1,这其实就是 BitBool。BitBool 基本上不存在在独立的数据类型,只是某种按存贮的方式。TSL 如果要和外部的语言的 Boolean 类型打交道,最可靠地方法是采用具体位数的整数。 Boolean 型的常量有两个:TRUE 表示为真,FALSE 表示为假。 在 TSL 中,除了 0 为假以外,NIL 类型、空字符串、空数组在作为逻辑判断的时候也是为假的。 #### TDateTime 日期类型是一种难以表达的类型,也许有的人说是用某年某月某日的表达方法不是很简单吗,但是计算机语言是无国界的,有的国家是用 12/30/2010 来表达 2010 年 12 月 31 日,有的国家则是用 2010-12-30 来表达,所以采用字符串的方式来描述是难以行得通的。 TSL 中采用数字来描述的日期类型,具体规则如下: 整数部分表示自从 1899 年 12 月 30 日以来经历的天数,小数部分表示一天中均匀的分割 24 小时的时间所形成的时间。 例如: 0 表示 1899 年 12 月 30 日 0:00 2.75 表示 1900 年 1 月 1 日下午 6:00 -1.25 表示 1899 年 12 月 29 日 6:00 要得到一个指定日期的日期值,可以通过如 StrToDate('2002-1-1')的方法获得。 如果要显示一个日期型,请参考相关函数,如 DateToStr,DateTimeToStr 等 TSL 还支持 20101231.0931T 表达 2012 年 12 月 31 日 9 点 31 分。 这种表达方式可以达到最高 10 毫秒的精度。没有小数点即为 0 点 0 分, 20111231T 则为 2011 年 12 月 31 日 0 点 0 分。 采用这样的方式,历史和未来的任何一天的时间都可以很容易地表达。这种表达方式也是一种国际标准,像 Object pascal 语言,Excel 等通用开发语言和工具中的日期类型也都采纳了这个标准。 其他语言的日期时间表达方式 大多语言和 TSL 的日期表达相近,也是从某天以来的天数,但是有的也存在基准时间点不同。 如 Excel 采用的日期标准和 TSL 语言相同。 而 MATLAB 的时间和 TSL 语言的时间相差一个常量,比天软大 693960,相当于 MATLAB 的日期从公元前 1900 年开始。 SQLServer 中的日期和 TSL 语言相差 1,基点为 1899 年 12 月 31 日开始。 有的语言采用从某个时间点以来发生的秒数作为日期时间的表达方式,这种表达除了基点 0 不同以外,一天的表达也相差了 24\*3600 倍。还有的语言,日期不是采用数据方式。例如 JAVA 这种语言,就是采用“对象”来表达日期的。 #### String 在 TSL 语言中,字符串常量的表达方式是采用单引号或者双引号括起来。例如 123 表示数值为 123 的整数,而"123"则表示内容为 123 的的字符串,是两种不同的数据类型。由于字符串中可能会包括一些特殊的字符,例如回车换行以及引号,就采用\符进行转义,例如\r 表示回车字符,\n 表示换行字符。采用\符进行转义后,字符串里的\字符就得用\\来表达了。例如'ab\\r\'d\r\n'表示的字符串内容是带回车换行结尾的 ab\r'd 字符串。 \转义的几个特殊字符为: \\表示\r 表示回车 \n 表示换行 \t 表示制表符 Tab \0 表示 ASCII 值为 0 的字符 \跟其他任何字符都为该字符的本身 因此,\'就是',\"就是" 字符串中引号的另一种表示方法 TSL 语言还支持在字符串常量中表达'或者"的另外的方式,例如字符串常量表达如下: 'This"s a book.' 这个表示字符串的内容为 This's a book. 在字符串常量中,连续的两个与字符串开始的引号相同的引号可代表一个引号。 也就是说,"This""s a book."代表 This"s a book.,但是"This''s a book."则代表的是 This''s a book. #### 号字符表达方式 有时候,程序中需要表达特殊的难以直接输入的 ASCII 符,例如笑脸符的 ASCII 值为 1,要表达的时候就用#1 就可以表达了,而同样的,回车符的 ASCII 码值为 13,可以用#13 来表达,而字符 0 的 ASCII 码值为 48,则#48 可以表达数字字符 0。 # 号字符表达方式可以和引号的字符串表达方式串起来表达字符串常量,例如:'The first line,Hello!'#13#10'The second line,Yeah!'#13#10'The End.'描述的字符串内容为: The first line,Hello! The seond line,Yeah! The End. TSL 字符串采用带长度的表示,可包含 ASCII 0 字符;理论上最大长度为 4G(受内存限制)。 ##### 字符串的表达 A:TSL 语言中,采用的是 GBK 编码。 一般用引号(单引号或双引号)"xxx"表示一个字符串,为多字节字符串,如: ```tsl s := "Hello 天软!"; ``` Unicode 字符串: 支持 L"xxx"方式表示一个 Unicode 字符串,也称宽字节字符串,如: ```tsl s := L"Hello 天软!"; ``` 字符串内转义\u 可以表达 unicode 字符,\u 后默认为 16 进制的 Unicode 码,如: ```tsl s := L"\u5929\u8F6F"; ``` 表示字符串 L"天软" ##### 在 Unicode 字符串连接中被自动识别为 Unicode 码,默认为 10 进制,因而需要使用 0x 代表 10 进制,如: ```tsl s := L"AA"#0x5929#0x8F6F ``` s 结果为 L"AA 天软" UTF8 字符串: 支持 U"xxx"方式表示一个 UTF8 字符串,如: ```tsl s := U"Hello 天软!"; ``` 也可以通过非转义方式描述: 如多字符字符串表示“我们” ```tsl s := %% 我们%%; ``` 宽字节字符串表示“我们” ```tsl s := L%% 我们%%; ``` UTF8 字符串表示“我们” ```tsl s := U%% 我们%%; ``` ##### ANSI 字符串、Unicode 字符串与 UTF8 字符串 TSL 语言默认的字符串均是 ANSI 类型的。 但在语言内核已经支持了 UNICODE,在字符串引号前加 L 就代表是一个 UNICODE 字符串。如 L”CCC”表明为 Unicode 的字符串”CCC”。 字符串内转义\u 可以表达 unicode 字符,\u 后默认为 16 进制的 UNicode 码,如 L"\u5929\u8F6F"表达 L"天软" # 在 Unicode 字符串连接中被自动识别为 Unciode 码,默认为 10 进制,因而需要用 0x 代表 16 进制,如 L""#0x5929#0x8F6F 表达 L"天软" TSL 许多字符串相关函数都支持 Unicode,函数版本一般是以 W 结尾,例如 InttoStrW(1)的结果是 L”1”。 WideString 函数可以把 ANSI 串转换为 UNICODE 串,例如 WideString(“AAA”)的结果是 L”AAA”。 类似的, String 函数可以把 Unicode 串转换为 MBCS 多字节 ANSI 串。在处理特殊的符号,以及一些特殊的中文时 UNICODE 具备一定的优势。 如果不特殊说明,缺省 TSL 字符串均是 ANSI 的。 Unicode 和 Ansi 字符串的运算返回以左操作数的类型为准,如"喜欢"+L"天软"的结果是"喜欢天软",L"喜欢"+"天软"的结果是 L"喜欢天软". TSL 语言中大多数的算符、基础函数及基类都支持 Unicode 字符串。如字符串的拼接、比较等运算,字符串的截取与转换等基础模型,数据库、文件、邮件等处理基类等。 TSL 语言没有独立的 UTF8 字符串类型,UTF8 字符串的本质就是一个字节串,也就是一种特殊的字符串。在绝大多数其他语言中也是如此。 但 TSL 语言对 UTF8 的常量串提供了支持,和 UNICODE 字符串的前导符 L 类似的,UTF8 字符串的字符前导为 U,例如 U"天软"表达的是 UTF8 串的天软。除此以外, TSL 还提供了丰富的函数支持 UTF8。 具体示例可参考:FAQ:字符串的表达 ##### 字符串转义 为了支持字符串包含一些特殊的字符,例如回车换行以及引号,就采用\符进行转义,例如\r 表示回车字符,\n 表示换行字符。 采用\符进行转义后,字符串里的\字符就得用\\来表达了。例如'ab\\r\'d\r\n'表示的字符串内容是带回车换行结尾的 ab\r'd 字符串。 \转义的几个特殊字符为: \\表示\ \r 表示回车 \n 表示换行 \t 表示制表符 Tab \x 之后跟 2 两个 16 进制字符,代表字符 ANSI 值,例如\x30 就是字符 0。 \u 之后跟 4 个 16 进制字符,对于 unicode 串而言表示 unicode 的值,对于 UTF8 串而言表示该 Unicode 值字符的 UTF8 串,对于 ansi 串而言代表两个字符。 \0 表示 ASCII 值为 0 的字符 \a 表示响铃符,等同于\x07 \b 表示回退符,等同于\x08 \f 表示换页符,等同于\x0c \v 表示垂直制表符,等同于\x0b \’表示’ \”表示” \跟其他非转义字符的值都为该字符的本身,而不会报错。但由于转义符号未来可能会 扩展,所以除了已知的转义以外,不应利用此特性混淆字符串 ##### 字符串的非转义表达%% 如果有程序代码或者其他多行的字符串,转移表达描述起来相当复杂, TSL 使用%%符来支持不需要转义的原始串, %%支持 UNICODE 和 UTF-8 的 L 和 U 前导串。 说明:定义一个字符串,字符串中的转义字符无效。 定义:%%[标识符]<回车换行|回车|tab|空格>字符串原始串%%[标识符] 注: 1、通过标识符进行配对,若没有,则配对第一个%%。 2、字符串中的任何转义字符都是无效的,比如%% a\r\nb%%它就是字符串'a\r\nb'。 例如: ```tsl %% \r\nABC%% ``` 代表字符串 `\\r\\nABC`,无标识符,字符串中包含 `\"` 等转义符号。 ```tsl %%__ printf("%%smc")%%__ ``` 代表字符串 `printf("%%smc")`,其中 `__` 为标识符。 ```tsl L%% abcd%% ``` 代表 Unicode 字符串 `L"abcd"`。 更多示例如: 范例 1:%%的用法 ```tsl a := %%f1 ABCDEFG%%f1; return a; ``` 结果:返回字符串 `ABCDEFG`。 ```tsl a := %%a ABCDE\\FG%%a; return a; ``` 结果:返回字符串 `ABCDE\\FG`。 范例 2:%%与引号的区别 ```tsl // 表示字符串 This's a book s := %%s1 This's a book %%s1; q := 'This\'s a book'; return s = q; ``` 结果:返回 1。 ```tsl // 路径中的应用 LJ := "C:\\Program Files\\Tinysoft\\Analyse.NETplug\\log"; LJ2 := %% C:\program Files\Tinysoft\Analyse.NETplug\log%%; return LJ = LJ2; ``` 结果:返回 1。 ##### 字符串中#表达 有时候,程序中需要表达特殊的难以直接输入的 ASCII 符,TSL 支持以#号加 ASCII 码来描述该字符。 例如笑脸符的 ASCII 值为 1,要表达的时候就用#1 就可以表达了, 而同样的,回车符的 ASCII 码值为 13,可以用#13 来表达,而字符 0 的 ASCII 码值为 48,则#48 可以表达 数字字符 0。 # 号字符表达方式可以和引号的字符串表达方式串起来表达字符串常量。 例如: ```tsl 'The first line,Hello!'#13#10'Thesecond line,Yeah!'#13#10' The End.' ``` 描述的字符串内容为: The first line,Hello! The seond line,Yeah! The End. #### Binary 二进度制类型,二进制类型是用来存贮文件等二进制流的数据类型,这种类型主要用于象生成位图以及在 CGI 应用中返回位图以及文件。 取二进制串里的字符或者设置指定下标的字符,使用[]操作符,下标从 0 开始。 ```tsl s[0] := "C"; s[1] := 0x30; // char '0' c := s[0]; ``` c 为长度 1 的字符串。 #### Array,TableArray 数组类型 数组型,数组是程序中最常用的结构数据类型,用来描述一定数目的元素集合。数组的每个元素和下标相关联,根据下标指示数组中元素的位置。 数组中的元素可以是任意类型的数据; 一个数组在使用之前,首先必须初始化为数组。数组支持自动扩展:设置新下标会扩展长度或维度。 ```tsl arr := array(); arr[0] := -1; arr[0][0][0] := 0; ``` TSL 的数组,有两种下标,一种为整数,一种为字符串。允许有字符型下标存在,其优点是可以直接描述一张数据表。例如 arrTable 是一个二维数组,我们可以设定其中的一个元素值如下: ```tsl arr_table[0]["日期1"] := "2002-04-15"; arr_table[0]["日期2"] := "2002-06-23"; ``` 这其中表示 arrTable 是一个二维数组,第一维为整数下标,第二维为字符串下标,这种类型的数组我们又称之为 TableArray,在系统中,象 Nday,NDay2 等函数以及 TGraph 的数据类型里依赖这种特殊的数组类型。 矩阵只是一种特殊的二维数字数组。 ##### 一维数组的理解 一维数组是按整数下标组织的有序元素集合,元素通过下标访问与修改。 ##### 多维数组的理解 多维数组由多层下标组成,每一维表示不同层级的索引,可视为“数组的数组”。 ##### 字符串也可以作为数组的下标 TSL 允许字符串作为下标,常用于表示表格型或键值型数据,便于按名称直接访问元素。 ##### 数组的表达方式 - `array(2, 3, 5, 7, 11)` 创建 0 起始的一维数组。 - `array(0:2, 1:3, 2:5, 3:7, 4:11)` 显式指定下标,与上例等价。 - `array("身高": 1.75, "体重": 85, "姓名": "李四")` 使用字符串下标。 - 多维数组可用嵌套表达,内部可省略 `array`。 - 数组项允许混合类型,也允许表达式作为元素。 示例: ```tsl a := array(2, 3, 5, 7, 11); b := array(0:2, 1:3, 2:5, 3:7, 4:11); c := array("身高": 1.75, "体重": 85, "姓名": "李四"); m := array((0, 1, 2, 3, 4), (3, 4, 5, 6, 7)); d := array(1 + 3, 2 + 5); empty := array(); ``` ##### Array of 类型注解(可选) 类型注解可用 `array of