Tea语言

Tea语言

Tea语言(Tea Programming Language)

一种新的编程语言,其规范即是语法,简洁易用,并具有简单的类型系统和单元模块系统。(A new programming language, whose specification is grammar, is simple and easy to use, and has simple type system and unit module system.)

1
2
// 来自深圳的问候
echo "世界你好!"

Tea语言目前有以下特点:

  • 是一个强规范的编程语言(规范即语法),拥有精炼简洁的语法,简约的类型系统和单元模块体系
  • 经过精心设计,力求让代码编写体验更轻松自然,让使用者可以更专注于创意实现
  • 基于单元模块(Unit)组织程序文件,任何程序文件都必须包含在某个Unit中,可引入使用外部Unit
  • 对字符串处理语法进行了特别设计,尤其方便用于WEB开发
  • 类型系统支持类型推断,并在类型兼容性方面有一些特别处理
  • 编译时将进行类型推断和语法检查,有助于提前发现相关问题
  • 通过编译生成PHP代码运行,并可调用PHP库

Tea语言由创业者Benny设计开发,潘春孟(高级工程师/架构师)与刘景能(计算机博士)参与了早期设计与测试使用。

   1 
---
   2 
# Tea语言(Tea Programming Language)
   3 
---
   4 
 
   5 
// 来自深圳的问候
   6 
echo "世界你好!"
   7 
 
   8 
---
   9 
## 01. 简要介绍
  10 
 
  11 
Tea语言目前有以下特点:
  12 
- 是一个强规范的编程语言(规范即语法),拥有精炼简洁的语法,简约的类型系统和单元模块体系
  13 
- 经过精心设计,力求让代码编写体验更轻松自然,让使用者可以更专注于创意实现
  14 
- 基于单元模块(Unit)组织程序文件,任何程序文件都必须包含在某个Unit中,可引入使用外部Unit
  15 
- 对字符串处理语法进行了特别设计,尤其方便用于WEB开发
  16 
- 类型系统支持类型推断,并在类型兼容性方面有一些特别处理
  17 
- 编译时将进行类型推断和语法检查,有助于提前发现相关问题
  18 
- 通过编译生成PHP代码运行,并可调用PHP库
  19 
 
  20 
Tea语言由创业者Benny设计开发,潘春孟(高级工程师/架构师)与刘景能(计算机博士)参与了早期设计与测试使用。
  21 
 
  22 
(本文档同时也是一个Tea语言程序,可被Tea语言编译器编译通过)
  23 
---
  24 
 
  25 
---
  26 
## 02. 基本语句
  27 
- 语句是Tea语言的基本语法之一
  28 
- Tea语言编译器基于语法的合理性识别语句
  29 
- 一个语句的各部分可分布于连续的多行中
  30 
- 在一行代码中有多个语句时需要分号间隔
  31 
---
  32 
 
  33 
// 带换行符结尾的字符串输出,支持输出多项
  34 
echo 'Hey,', 'Who are you?' // 相当于print 'Hey,', 'Who are you?', "\n"
  35 
 
  36 
// 不带换行符结尾的字符串输出,支持输出多项
  37 
// 这里的NL是内置常量,被定义为 "\n"
  38 
print 'string1', 'string2', NL
  39 
 
  40 
// 返回,可带一个参数,或不带任何参数
  41 
// 可用于函数/方法中返回数据,也可用于被#include的程序文件中返回数据
  42 
// return 123
  43 
 
  44 
// 退出进程,可带一个Int参数,或不带任何参数
  45 
// exit 0
  46 
 
  47 
---
  48 
## 03. 类型
  49 
- 简单类型 String、UInt、Int、Float、Bool
  50 
- 复合类型 Array、Dict、Object
  51 
- 特别类型 Any、XView、Regex、Iterable、Callable
  52 
- XView是Tea语言特有的一种类型,这种类型量可接受采用HTML/XML标签定义的块作为值,也可接受IView接口的类实例作为值
  53 
- Any类型量可接受任意类型的值
  54 
- String类型量被设计为可接受Int、UInt、XView类型值
  55 
- UInt在表达成PHP代码后其实是Int类型,其最大值与Int的一致,皆为PHP_INT_MAX
  56 
    为什么需要有UInt类型?因为我们在实践中发现,正整数非常常用。
  57 
    需要注意的是,UInt类型变量在发生减法运算后,值可能是负数,并不能严格保证为正整数,这需要在程序中做好处理。
  58 
- Array为纯索引数组(称为数组),Dict为纯关联数组(称为字典),这与PHP中有所不同
  59 
- Object为对象类型,目前只能通过创建类的实例获得
  60 
- Regex为正则表达式类型,用于简化正则表达式写法
  61 
- Iterable为可迭代类型,可接受Array、Dict、IteratorInterface的值或对象作为值
  62 
- Callable为可调用类型,可接受普通函数和匿名函数作为值
  63 
---
  64 
 
  65 
// Any 可接受任何类型值
  66 
var any Any
  67 
any = 1
  68 
any = []
  69 
any = 'abc'
  70 
 
  71 
// 将Any类型值转换成String类型
  72 
var str_from_any = any as String
  73 
 
  74 
// String
  75 
var str String = 'Unescaped string\n'   // 单引号字符串,\n\t\r等字符将当作字面字符
  76 
str = "Escaped string\n"                // 双引号字符串,将处理转义字符
  77 
str_with_interpolation = 'Unescaped string with interpolation ${5 * 6}' // 单双引号字符串均支持插值,带$插值的字符串,不转义HTML字符
  78 
str_with_interpolation = "Escaped string with interpolation ${5 * 6}\n"
  79 
 
  80 
xss = '<script>alert("XSS!")</script>'
  81 
html_escaped_interpolation = "The html-escaped string: #{xss}" // 带#插值的字符串,将转义HTML字符
  82 
text_labeled = #text "would not process interpolation ${5 * 6}" // 以#text标记的字符串,其中插值表达式将不被处理
  83 
 
  84 
// 类似对象一样的调用String伪对象属性或方法
  85 
str.length // 字符串长度(表达成PHP代码后是iconv_strlen,使用PHP配置的字符集计算)
  86 
str.slice(0, 3) // 字符串截取(表达成PHP代码后是iconv_substr,使用PHP配置的字符集计算截取)
  87 
 
  88 
var uint_num UInt = 123
  89 
var int_num Int = -123
  90 
var float_num Float = 123.01
  91 
var bool Bool = true
  92 
 
  93 
// XView在做Web视图开发时尤其方便
  94 
var xview XView = <div>
  95 
    <h1>XView是什么?</h1>
  96 
    <p>XView类似字符串,但无需引号,可以直接按HTML标签方式编写</p>
  97 
    <p>Interpolation with origin ${uint_num * 10}</p>
  98 
    <p>Interpolation with html-escaped #{xss}</p>
  99 
</div>
 100 
 
 101 
// 正则表达式
 102 
var regex Regex = /^[a-z0-9'_"]+$/i
 103 
if preg_match(regex, 'Abc\'123"') {
 104 
    echo 'matched!'
 105 
}
 106 
 
 107 
// 元素类型为Any的数组
 108 
var any_array Array = [123, 'Hi', false, [1, 2, 3]]
 109 
 
 110 
// 元素类型为Int的数组
 111 
var int_array Int.Array = []    // 初始化为空数组
 112 
int_array = [-1, 10, 200]
 113 
int_array.length        // 获取数组元素个数
 114 
int_array.slice(0, 2)  // 截取数组片段
 115 
 
 116 
// 字典类型的Key无需定义类型,支持String/Int
 117 
// Value类型为String的字典
 118 
var str_dict String.Dict = [:] // 初始化为空字典
 119 
str_dict = [
 120 
    'k1': 'value for string key "k1"',
 121 
    123: 'value for int key "123"'
 122 
]
 123 
 
 124 
// 元素类型为String.Dict的数组
 125 
var str_dict_array String.Dict.Array = [
 126 
    ['k0': 'v0', 'k1': 'v01'],
 127 
    str_dict
 128 
]
 129 
 
 130 
---
 131 
## 04. 修饰符
 132 
- Tea语言中有public、internal、protected、private四种修饰符
 133 
- 四种修饰符均可用于类成员的声明/定义
 134 
- public、internal可用于类、接口、独立常量、独立函数的声明/定义
 135 
- public修饰的可被外部Unit调用
 136 
- internal修饰的只能被本Unit调用
 137 
- protected修饰的类成员可被继承的类调用
 138 
- private修饰的类成员只能被本类调用
 139 
---
 140 
 
 141 
---
 142 
## 05. 常量
 143 
- 常量声明/定义必须以internal/public修饰符开始
 144 
- 常量作用域为Unit级别,声明为public的可以被其它Unit引入使用
 145 
- 常量名必须为大写,以[A-Z_]开始,可包括[A-Z0-9_]
 146 
---
 147 
 
 148 
// internal修饰的常量,只能在本Unit中调用
 149 
internal STRING_CONST = 'abcdefg'
 150 
 
 151 
// public修饰的常量,可在其它Unit中调用
 152 
public PI = 3.1415926
 153 
 
 154 
// 可使用Array/Dict字面量作为常量的值
 155 
public ARRAY_CONST = [1, 2]
 156 
 
 157 
---
 158 
## 06. 变量
 159 
- Tea语言不支持自定义全局变量,变量均为局部作用域
 160 
- 变量名必须为小写,可由 a-z0-9_ 字符组成
 161 
- 使用var关键字声明/定义变量,可标注类型
 162 
- 变量亦可无需定义直接赋值使用,此时变量类型将自动推断为所赋值的类型
 163 
---
 164 
 
 165 
// 声明一个变量并赋初始值
 166 
var str1 = 'Hi!' // 此用例将自动推断成String类型
 167 
 
 168 
// 声明一个String类型的变量
 169 
var str2 String
 170 
 
 171 
// 直接赋值给一个未经声明的变量
 172 
var_without_decared = 123 // 此用例将自动推断成UInt类型
 173 
 
 174 
---
 175 
## 07. 运算符
 176 
- 运算符的优先级和结合方向在不同语言中有不同的规则,Tea语言试图简化这些规则,并尽可能让其在使用时显得更自然
 177 
- 访问运算符优先级最高,除逻辑非(not)以外的一元运算符和类型转换符优先级排第二
 178 
- 结合方向,前置一元运算符为右结合,二元运算符为左结合
 179 
- 三元运算符嵌套使用时必须加括号,故无需考虑结合方向
 180 
- Tea语言不支持赋值运算作为子表达式,故无需考虑其优先级和结合方向
 181 
- Tea语言中不支持“--”、“++”等前置和后置运算符,因考虑其可在子表达式中改变值,易产生难以被发现的问题
 182 
 
 183 
    优先级 运算符
 184 
    1   .  ->  ()  []                   访问符
 185 
    2   ~  -  as                        一元运算、类型转换
 186 
    3   **                              幂运算
 187 
    4   * / % << >> &                   数学运算、按位左移、按位右移、按位与
 188 
    5   +  -  |  ^                      数学运算、按位或、按位异或
 189 
    6   concat  merge                   String/Array连接、Array/Dict按index/key合并
 190 
    7   <=> < <= > >= != !== == === is  比较运算
 191 
    8   not                             逻辑非
 192 
    9   and                             逻辑与
 193 
    10  or                              逻辑或
 194 
    11  ??                              none合并
 195 
    12  condition ? exp1 : exp2         三元条件表达式
 196 
 
 197 
---
 198 
 
 199 
// 值得注意的是,“**”运算符在一些语言中优先级比一元运算符高,且大多为右结合
 200 
// 而在Tea语言中,为简化规则考虑,“**”运算符优先级比一元前置运算符“~”和“-”低,且为左结合
 201 
var pow_result = -2 ** 3 ** 5 // 相当于 ((-2) ** 3) ** 5
 202 
 
 203 
// 连接运算符,可用于字符串/数组
 204 
// 很多语言使用“+”进行连接运算,但数值相加与字符串/数组连接的语义有所不同,我们认为这在一些场景下不太清晰
 205 
// Tea语言使用concat关键字作为连接运算符,其优先级比数学运算符、按位运算符低
 206 
// 为什么不使用类似PHP一样的“.”作为连接运算符?因为“.”已经用于访问运算符了
 207 
// 字符串连接运算在Tea语言中可能会极少用到,因为Tea语言提供了非常便捷的字符串插值语法
 208 
var string_concat = 'abc' concat 1 + 8 & 2 * 3 // 相当于 'abc' concat (1 + (8 & 2) * 3)
 209 
var array_concat = ['A', 'B'] concat ['A1', 'C1'] // result: ['A', 'B', 'A1', 'C1']
 210 
 
 211 
// 合并运算符,可用于数组/字典
 212 
var array_merge = ['A', 'B'] merge ['A1', 'B1'] // result: ['A1', 'B1']
 213 
var dict_merge = ['a': 'A', 'b': 'B'] merge ['a': 'A1', 'c': 'C1'] // result: ['a': 'A1', 'b': 'B', 'c': 'C1']
 214 
 
 215 
// as运算符,当用于基础类型时,将进行类型转换
 216 
var int_from_string = '123' as Int // 相当于PHP中 (int)'123'
 217 
var uint_from_string = '-123' as UInt // 相当于PHP中 abs('-123')
 218 
var str_from_uint = 123 as String
 219 
var str_from_int = -123 as String
 220 
var str_from_float = 123.123 as String
 221 
 
 222 
// as运算符,当用于类时,将只被用于编译器类型系统检查处理,而不会进行任何转换
 223 
var ex1 Any
 224 
var ex2 = ex1 as Exception
 225 
 
 226 
// is运算符,可用于检查变量是否为某个基础类型,或是否是某个类的实例
 227 
1.1 is Int // false
 228 
1 is Int  // true
 229 
2 is UInt // true
 230 
ErrorException('Some') is Exception // true
 231 
 
 232 
// Tea语言中的逻辑非运算符优先级排在比较运算符之后,与其它语言不一致
 233 
var not_result = not uint_num > 3 // 相当于 not (uint_num > 3)
 234 
 
 235 
// PHP的三元运算符是左结合的,而其它大部分语言中为右结合
 236 
// Tea语言中多个三元运算表达式嵌套使用时,必须加括号,无需考虑结合方向
 237 
var ternary_result = uint_num == 1 ? 'one' : (uint_num == 2 ? 'two' : (uint_num == 3 ? 'three' : 'other'))
 238 
 
 239 
---
 240 
## 08. 流程控制和异常处理结构
 241 
- Tea语言支持 if条件分支、case条件分支、for-in迭代遍历、for-to/downto区间循环、while条件循环、try异常处理 等结构
 242 
- C风格 for (;;;) 风格循环语句很灵活,但没有被支持,因其易被写出预料之外的代码
 243 
- 我们在尝试将else、elseif、catch、finally这些副语句块与上述主语句块混搭,这样是不是有点意思?至于好不好,待使用看看吧😄
 244 
- 目前除了while语句之外的语句都支持elseif、else语句块
 245 
- 目前所有结构都支持catch、finally异常处理语句块
 246 
---
 247 
 
 248 
a = 0
 249 
b = 1
 250 
 
 251 
if a {
 252 
    //
 253 
}
 254 
elseif b {}
 255 
else {}
 256 
catch ex ErrorException {}
 257 
catch ex {}
 258 
finally {}
 259 
 
 260 
// Iterable类型量都可以使用for-in遍历
 261 
for k, v in str_dict {
 262 
    // do sth.
 263 
}
 264 
else {
 265 
    echo 'dict is empty'
 266 
}
 267 
 
 268 
// 顺序的区间循环
 269 
for i = 0 to 9 {
 270 
    //
 271 
}
 272 
else {}
 273 
 
 274 
// 倒序的区间循环
 275 
for i = 9 downto 0 step 2 {
 276 
    //
 277 
}
 278 
 
 279 
// 带标签的两层嵌套while循环
 280 
// 可在break/continue后面带上标签标明break/continue指令的目标
 281 
i = 0
 282 
#outer_loop while 1 {
 283 
    #inner_loop while true {
 284 
        i = i + 1
 285 
        if i > 10 {
 286 
            break #outer_loop
 287 
        }
 288 
        else {
 289 
            continue #inner_loop
 290 
        }
 291 
    }
 292 
}
 293 
catch ex {}
 294 
 
 295 
---
 296 
## 09. 函数
 297 
- 函数声明/定义必须以internal/public修饰符开始
 298 
- 函数作用域为Unit级别,声明为public的可以被其它Unit引入使用
 299 
- Tea语言函数名规范为小写,必须以[a-z_]开始,可包括[a-z0-9_]
 300 
- 如果为PHP函数,可使用大写字母,但首字符仍必须为小写字母
 301 
---
 302 
 
 303 
// internal修饰的函数,只能在本Unit中调用
 304 
internal demo_function1(message String) {
 305 
    echo 'this function can only be called by local unit'
 306 
}
 307 
 
 308 
// public修饰的函数,可在其它Unit中调用
 309 
public demo_function2(message String = 'with a default value') {
 310 
    echo 'this function can be called by local or foriegn units'
 311 
}
 312 
 
 313 
// 带返回类型标注的函数
 314 
public demo_function_with_a_return_type(some String) UInt {
 315 
    return some.length
 316 
}
 317 
 
 318 
// 带回调的函数
 319 
public demo_function_with_callbacks(some String) String -> success(message String) String -> failure(error) {
 320 
    var success_callback_result
 321 
    if success {
 322 
        success_callback_result = success('Success!')
 323 
    }
 324 
 
 325 
    if failure {
 326 
        failure('Some errors.')
 327 
    }
 328 
 
 329 
    return "the success callback result is: $success_callback_result"
 330 
}
 331 
 
 332 
// 调用一个普通函数
 333 
var ret1 = demo_function_with_a_return_type('some data')
 334 
 
 335 
// 调用带回调的函数
 336 
var ret2 = demo_function_with_callbacks('some data') -> success(message) {
 337 
    echo message
 338 
    return 'some return data'
 339 
} -> failure(error) {
 340 
    echo error
 341 
}
 342 
 
 343 
---
 344 
## 10. 类与接口
 345 
- 类/接口定义必须以internal/public修饰符开始
 346 
- 类/接口作用域为Unit级别,声明为public的可以被其它Unit引入使用
 347 
- 类/接口名必须以大写字母开始,可包括[A-Za-z0-9_]
 348 
- 类/接口成员的命名规范与常量、变量、函数一致
 349 
- 接口名风格1:以字母I作为前缀,并且第二个字母必须为大写
 350 
- 接口名风格2:以字母Interface作为后缀
 351 
- 满足接口名风格的将被编译器认为是接口,否则被认为是普通类
 352 
- Tea语言的接口相当于是PHP中Interface和Trait的结合,实际上在编译生成的目标代码中的确由这两部分组成
 353 
- Tea语言的接口中可以有代码实现,甚至可以声明属性,和非public成员!(这和传统面向对象语言有所不同,这样的改变真的好吗?我暂时不太确定)
 354 
---
 355 
 
 356 
// 这是一个I前缀风格的接口
 357 
public IDemo {
 358 
    // 这是一个类常量,未标注修饰符,默认为public,可被外部Unit调用
 359 
    CONST1 = 'This is a constant!'
 360 
 
 361 
    // 这是一个静态属性
 362 
    static a_static_prop = "a static property."
 363 
 
 364 
    // 这是一个静态方法
 365 
    static say_hello_with_static(name String = 'Benny') {
 366 
        print "Hello, $name\n"
 367 
    }
 368 
}
 369 
 
 370 
// 这是一个Interface后缀风格的接口
 371 
internal DemoInterface {
 372 
    // 这是一个实例属性
 373 
    message String = 'hei~'
 374 
 
 375 
    // 这是一个未带实现的实例方法声明
 376 
    set_message(message String)
 377 
 
 378 
    // 这是一个实例方法
 379 
    get_message() String {
 380 
        return this.message
 381 
    }
 382 
}
 383 
 
 384 
internal DemoBaseClass {
 385 
    // 构造函数
 386 
    construct(name String) {
 387 
        echo "Hey, $name, it is constructing..."
 388 
    }
 389 
 
 390 
    // 析构函数
 391 
    destruct() {
 392 
        echo "it is destructing..."
 393 
    }
 394 
 
 395 
    protected a_protected_method() {
 396 
        //
 397 
    }
 398 
}
 399 
 
 400 
// 本类继承了DemoBaseClass类,并实现了IDemo和DemoInterface接口
 401 
// 本类使用public修饰,可被外部Unit调用
 402 
public DemoPublicClass: DemoBaseClass, IDemo, DemoInterface {
 403 
    // 实现DemoInterface中的方法
 404 
    set_message(message String) {
 405 
        this.message = message
 406 
    }
 407 
}
 408 
 
 409 
// 创建一个对象
 410 
var object = DemoPublicClass('Benny')
 411 
 
 412 
// 调用实例方法
 413 
object.set_message('some string')
 414 
 
 415 
// 调用静态方法
 416 
object.say_hello_with_static()
 417 
DemoPublicClass.say_hello_with_static()
 418 
 
 419 
---
 420 
## 11. 标签(Label)
 421 
- Tea语言使用#作为语法的一部分,称为“标签”,即“Label”
 422 
- 预定义的标签有:#tea #php #unit #use #main #expect #include #text 等,其中#tea标签用于内部用途,其它分别有不同用途
 423 
---
 424 
 
 425 
---
 426 
## 12. 单元模块
 427 
- 使用#unit标签声明单元模块(Unit)
 428 
- 每个Unit拥有一个独立的名称空间,Unit内部不支持定义名称空间
 429 
- Unit用于将程序内容作用域与外部隔离,声明为public的常量、函数、类和接口可被外部Unit调用,声明为internal的只能在Unit内部调用
 430 
- 在指定目录中创建“__unit.tea”文件,并在文件的开始写上类似 "#unit tealang.org/demo" 即定义了一个Tea Unit,#unit后边的URI即为这个Unit的名称空间
 431 
- 该单元模块的目录名称,须与#unit所声明的名称空间完全匹配,编译器将根据名称空间查找所在目录(可参考tests/xview)
 432 
- 使用#use标签引入外部Unit中的类,以供当前程序调用,如:"#use tealang.org/libs { DemoClass1, DemoClass2 }"
 433 
- #use标签目前仅限于在声明文件中使用(包括__unit.th和__public.th),后续可能会开放给*.tea程序文件使用
 434 
---
 435 
 
 436 
---
 437 
## 13. 将程序文件设置为入口
 438 
- 在目标Tea语言程序文件的开头加上#main标签,即可声明该程序文件为“入口程序”
 439 
- 当前程序文件的编译结果中将自动加上依赖项加载语句
 440 
- 当前Unit的编译结果中将自动加上内置库加载语句
 441 
---
 442 
 
 443 
#main // set current file as a main program
 444 
 
 445 
---
 446 
## 14. 使用无名称空间的PHP库
 447 
- 使用#php标签声明无名称空间的PHP常量、函数、类、接口和超全局变量,以供Tea语言程序调用
 448 
- 支持包括PHP内置的,也包括用户自定义的
 449 
- 对于用户自定义的,需要自行添加相关的加载语句
 450 
---
 451 
 
 452 
// 声明一个PHP内置超全局变量
 453 
#php $_ENV Dict
 454 
 
 455 
// 声明一个PHP内置常量
 456 
#php __CLASS__ String
 457 
 
 458 
// 声明一个PHP内置函数
 459 
#php phpinfo() Void
 460 
 
 461 
// 声明一个PHP内置类
 462 
#php BadFunctionCallException: Exception {
 463 
    public getCode() Int
 464 
    public getMessage() String
 465 
}
 466 
 
 467 
---
 468 
## 15. 使用有名称空间的PHP库
 469 
- 在所在库的目录中创建“__public.th”文件,并在文件的开始写上类似 "#unit NS1/NS2/NS3",即定义了一个可被Tea语言调用的Unit
 470 
- 代码库所在目录名称,须与#unit所声明的名称空间完全匹配,编译器将根据名称空间查找所在目录(可参考tests/PHPDemoUnit)
 471 
---
 472 
 
 473 
---
 474 
## 16. 标识符强规范
 475 
- Tea语言特点之一是标识符强命名规范,标识符包括变量名、常量名、函数名、类名、接口名等,区分大小写
 476 
- Tea语言中没有class、interface、function、const等关键字,编译器根据标识符风格来识别常量、函数、类和接口、属性、方法等
 477 
- 标识符前缀为下划线时,约定只能使用一个下划线作为前缀,双下划线前缀被编译器保留使用
 478 
- 标识符强编码规范有助于保持一致的代码风格,有助于更快速、更清晰的阅读理解代码
 479 
---
 480 
 
 481 
---
 482 
## 17. 运算符强规范
 483 
- 空格(包括“ ”、换行、制表符)是Tea语言语法的一部分,被用于分割语法元素
 484 
- 一元前置运算符前面须至少有一个空格
 485 
- 非访问运算的二元运算符(如+、-、*、/等)两端须至少各有一个空格
 486 
- 函数括号“(”、数组元素访问中括号“[”前面不能有空格
 487 
- 运算符强编码规范有助于保持一致的代码风格,也有助于更快速、更清晰的阅读理解代码
 488 
---
 489 
 
 490 
---
 491 
## 18. 代码注释语法
 492 
Tea语言支持三种注释语法,分别用于不同场景
 493 
- 文档专用注释,由三个连字符开启和结束,左边空字符须一致,如本节说明内容即使用了文档专用注释
 494 
- 单行注释  // inline comment
 495 
- 多行注释  /* multi-lines comments */
 496 
---
 497 
 
 498 
---
 499 
## 19. 安装和使用
 500 
- 安装PHP7.3运行环境
 501 
- 安装好PHP后,将PHP执行文件所在目录添加到操作系统环境变量中
 502 
- 在命令终端将当前目录切换到tea目录中,运行命令“php bin/tea documents”即可编译本文档程序
 503 
- 如使用Mac或Linux系统,可执行“chmod +x bin/*”将bin目录中程序设置为可执行,然后运行命令“bin/tea documents”即可进行编译
 504 
- 在dist/documents目录中可看到编译生成的目标文件
 505 
---
 506 
 
 507 
---
 508 
## 20. 致谢
 509 
Tea语言从众多优秀的编程语言中获取到设计灵感,主要包括(排名不分先后):
 510 
    PHP、Hack、JavaScript、TypeScript、Python、Swift、Kotlin、Go、Rust、Ruby、Java、C#、Pascal、C、Julia等。
 511 
在此向设计和维护这些编程语言的大师们致敬。
 512 
---
 513 
 
 514 
// document end
# Tea

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×