Skip to content

Commit

Permalink
#145 #147
Browse files Browse the repository at this point in the history
  • Loading branch information
xushiwei committed May 28, 2017
1 parent 7392151 commit c7631d9
Show file tree
Hide file tree
Showing 76 changed files with 283 additions and 239 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import (
"fmt"

"qlang.io/cl/qlang"
_ "qlang.io/qlang/builtin" // 导入 builtin 包
_ "qlang.io/lib/builtin" // 导入 builtin 包
)

const scriptCode = `x = 1 + 2`
Expand Down
87 changes: 44 additions & 43 deletions README_QL.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ x, y, z = [1, 2, 3]
举个例子:

```go
f, err = os.open(fname)
f, err = os.Open(fname)
```

这个例子,在 Go 里面返回的是 (*os.File, error)。但是 qlang 中是 var slice。
Expand Down Expand Up @@ -375,19 +375,19 @@ println(type(x1), type(x2))
是的,qlang 也支持 defer。这在处理系统资源(如文件、锁等)释放场景非常有用。一个典型场景:

```go
f, err = os.open(fname)
f, err = os.Open(fname)
if err != nil {
// 做些出错处理
return
}
defer f.close()
defer f.Close()

// 正常操作这个 f 文件
```

值得注意的是:

在一个细节上 qlang 的 defer 和 Go 语言处理并不一致,那就是 defer 表达式中的变量值。在 Go 语言中,所有 defer 引用的变量均在 defer 语句时刻固定下来(如上面的 f 变量),后面任何修改均不影响 defer 语句的行为。但 qlang 是会受到影响的。例如,假设你在 defer 之后,调用 f = nil 把 f 变量改为 nil,那么后面执行 f.close() 时就会 panic。
在一个细节上 qlang 的 defer 和 Go 语言处理并不一致,那就是 defer 表达式中的变量值。在 Go 语言中,所有 defer 引用的变量均在 defer 语句时刻固定下来(如上面的 f 变量),后面任何修改均不影响 defer 语句的行为。但 qlang 是会受到影响的。例如,假设你在 defer 之后,调用 f = nil 把 f 变量改为 nil,那么后面执行 f.Close() 时就会 panic。

### 匿名函数

Expand Down Expand Up @@ -430,10 +430,10 @@ defer fn {

```go
Foo = class {
fn setAB(a, b) {
fn SetAB(a, b) {
this.a, this.b = a, b
}
fn getA() {
fn GetA() {
return this.a
}
}
Expand All @@ -443,8 +443,8 @@ Foo = class {

```go
foo = new Foo
foo.setAB(3, "hello")
a = foo.getA()
foo.SetAB(3, "hello")
a = foo.GetA()
println(a) // 输出 3
```

Expand Down Expand Up @@ -478,20 +478,20 @@ go println("this is a goroutine")
一个比较复杂的例子:

```go
wg = sync.waitGroup()
wg.add(2)
wg = sync.NewWaitGroup()
wg.Add(2)

go fn {
defer wg.done()
defer wg.Done()
println("in goroutine1")
}

go fn {
defer wg.done()
defer wg.Done()
println("in goroutine2")
}

wg.wait()
wg.Wait()
```

这是一个经典的 goroutine 使用场景,把一个 task 分为 2 个子 task,交给 2 个 goroutine 执行。
Expand Down Expand Up @@ -600,9 +600,9 @@ qlang 采用微内核设计,大部分你看到的功能,都通过 Go package

```go
import (
"qlang.io/qlang/math"
"qlang.io/qlang/strconv"
"qlang.io/qlang/strings"
"qlang.io/lib/math"
"qlang.io/lib/strconv"
"qlang.io/lib/strings"
...
)

Expand All @@ -626,7 +626,7 @@ qlang.Import("", math.Exports) // 如此,你就可以直接用 sin 而不是 m

### 制作 qlang 模块

制作 qlang 模块的成本极其低廉。我们打开 `qlang.io/qlang/strings` 看看它是什么样的:
制作 qlang 模块的成本极其低廉。我们打开 `qlang.io/lib/strings` 看看它是什么样的:

```go
package strings
Expand All @@ -636,25 +636,26 @@ import (
)

var Exports = map[string]interface{}{
"contains": strings.Contains,
"index": strings.Index,
"indexAny": strings.IndexAny,
"join": strings.Join,
"title": strings.Title,
"toLower": strings.ToLower,
"toTitle": strings.ToTitle,
"toUpper": strings.ToUpper,
"trim": strings.Trim,
"reader": strings.NewReader,
"replacer": strings.NewReplacer,
"Contains": strings.Contains,
"Index": strings.Index,
"IndexAny": strings.IndexAny,
"Join": strings.Join,
"Title": strings.Title,
"ToLower": strings.ToLower,
"ToTitle": strings.ToTitle,
"ToUpper": strings.ToUpper,
"Trim": strings.Trim,

"NewReader": strings.NewReader,
"NewReplacer": strings.NewReplacer,
...
}
```

值得注意的一个细节是,我们几乎不需要对 Go 语言的 strings package 中的函数进行任何包装,你只需要把这个函数加入到导出表(Exports)即可。你也无需包装 Go 语言中的类,比如上面的我们导出了 strings.NewReplacer,但是我们不必去包装 strings.Replacer 类。这个类的所有功能可以直接使用。如:

```go
strings.replacer("?", "!").replace("hello, world???") // 得到 "hello, world!!!"
strings.NewReplacer("?", "!").Replace("hello, world???") // 得到 "hello, world!!!"
```

这是 qlang 最强大的地方,近乎免包装。甚至,你可以写一个自动的 Go package 转 qlang 模块的工具,找到 Go package 所有导出的全局函数,加入到 Exports 表即完成了该 Go package 的包装,几乎零成本。
Expand Down Expand Up @@ -691,9 +692,9 @@ var Exports = map[string]interface{}{
这样你就可以在 qlang 里面使用这个结构体:

```go
bar = &foo.Bar{x: 1, y: "hello"}
x = bar.getX()
y = bar.y
bar = &foo.Bar{X: 1, Y: "hello"}
x = bar.GetX()
y = bar.Y
println(x, y)
```

Expand Down Expand Up @@ -789,14 +790,14 @@ maxPrimeOf = fn(max) {

// Usage: maxprime <Value>
//
if len(os.args) < 2 {
fprintln(os.stderr, "Usage: maxprime <Value>")
if len(os.Args) < 2 {
fprintln(os.Stderr, "Usage: maxprime <Value>")
return
}

max, err = strconv.parseInt(os.args[1], 10, 64)
max, err = strconv.ParseInt(os.Args[1], 10, 64)
if err != nil {
fprintln(os.stderr, err)
fprintln(os.Stderr, err)
return 1
}
if max < 8 { // <8 的情况下,可直接建表,答案略
Expand Down Expand Up @@ -925,19 +926,19 @@ main { // 使用main关键字将主程序括起来,是为了避免其中用的
calc = new Calculator
engine, err = interpreter(calc, nil)
if err != nil {
fprintln(os.stderr, err)
fprintln(os.Stderr, err)
return 1
}

scanner = bufio.scanner(os.stdin)
for scanner.scan() {
line = strings.trim(scanner.text(), " \t\r\n")
scanner = bufio.NewScanner(os.Stdin)
for scanner.Scan() {
line = strings.Trim(scanner.Text(), " \t\r\n")
if line != "" {
err = engine.eval(line)
err = engine.Eval(line)
if err != nil {
fprintln(os.stderr, err)
fprintln(os.Stderr, err)
} else {
printf("> %v\n\n", calc.ret())
printf("> %v\n\n", calc.Ret())
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion cl/ctrl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"testing"

"qlang.io/cl/qlang"
_ "qlang.io/qlang/builtin"
_ "qlang.io/lib/builtin"
)

// -----------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion cl/function_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"testing"

"qlang.io/cl/qlang"
_ "qlang.io/qlang/builtin"
_ "qlang.io/lib/builtin"
)

// -----------------------------------------------------------------------------
Expand Down
6 changes: 3 additions & 3 deletions cl/goroutine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"testing"

"qlang.io/cl/qlang"
_ "qlang.io/qlang/builtin"
_ "qlang.io/qlang/chan"
"qlang.io/qlang/sync"
_ "qlang.io/lib/builtin"
_ "qlang.io/lib/chan"
"qlang.io/lib/sync"
)

func init() {
Expand Down
2 changes: 1 addition & 1 deletion cl/module_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"testing"

"qlang.io/cl/qlang"
_ "qlang.io/qlang/builtin"
_ "qlang.io/lib/builtin"
)

// -----------------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions cl/qlang/engine2.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ func SetAutoCall(t reflect.Type) {
//
var Exports = map[string]interface{}{
"new": New,
"New": New,
}

// -----------------------------------------------------------------------------
2 changes: 1 addition & 1 deletion cl/qlang_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"testing"

"qlang.io/cl/qlang"
"qlang.io/qlang/math"
"qlang.io/lib/math"
qspec "qlang.io/spec"
)

Expand Down
2 changes: 1 addition & 1 deletion cl/var_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"testing"

"qlang.io/cl/qlang"
_ "qlang.io/qlang/builtin"
_ "qlang.io/lib/builtin"
ql "qlang.io/spec"
)

Expand Down
30 changes: 15 additions & 15 deletions cmd/eql/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,20 +117,20 @@ $$

## eql 函数

### eql.imports()
### eql.Imports()

这个函数解析 imports 变量(通常是用户通过命令行 `--imports=package1,package2,...` 传入的)并将 `,` 分隔风格改为符合 Go 语言中 import (...) 风格的字符串。

如果 imports 变量不存在,则该函数返回 "" (空字符串)。

例如,我们假设传入的 imports 变量为 "bufio,bytes",则 `eql.imports()` 为如下风格的字符串:
例如,我们假设传入的 imports 变量为 "bufio,bytes",则 `eql.Imports()` 为如下风格的字符串:

```go
"bufio"
"bytes"
```

### eql.var("varname", defaultval)
### eql.Var("varname", defaultval)

这个函数主要解决 qlang 中目前还没有支持判断一个变量是否存在的缺陷。其语义看起来是这样的:

Expand All @@ -142,7 +142,7 @@ if varname != undefined {
}
```

当然目前因为在 qlang 中如果 varname 不存在就会直接报错,所以以上代码仅仅是表达 `eql.var("varname", defaultval)` 的逻辑语义。
当然目前因为在 qlang 中如果 varname 不存在就会直接报错,所以以上代码仅仅是表达 `eql.Var("varname", defaultval)` 的逻辑语义。

## 用 eql 实现 Go 对泛型的支持

Expand All @@ -152,7 +152,7 @@ if varname != undefined {
package eql_test

import (
<%= eql.imports() %>
<%= eql.Imports() %>
"encoding/binary"
)

Expand Down Expand Up @@ -281,19 +281,19 @@ func (p modbufio) flush(out *bufio.Writer) {
### 初始化

```go
ql = qlang.new()
eql = eqlang.new(ql)
ql = qlang.New()
eql = eqlang.New(ql)

ql.resetVars(map[string]var{"name": "qlang"}) // 重置 ql 对象的变量集合
ql.setVar("a", 123)
ql.ResetVars(map[string]var{"name": "qlang"}) // 重置 ql 对象的变量集合
ql.SetVar("a", 123)
```

### eql.subst("template text")
### eql.Subst("template text")

替换 $varname 为对应的值。例如:

```go
output = eql.subst("Hello, $name!")
output = eql.Subst("Hello, $name!")
println(output)
```

Expand All @@ -303,7 +303,7 @@ println(output)
Hello, qlang!
```

### eql.execute("template script", fname, output)
### eql.Execute("template script", fname, output)

执行 eql 模板。

Expand All @@ -313,7 +313,7 @@ Hello, qlang!
例如:

```go
eql.execute("Hello, <%= strings.toUpper(name) %>!\n", "", "")
eql.Execute("Hello, <%= strings.ToUpper(name) %>!\n", "", "")
```

输出为:
Expand All @@ -322,14 +322,14 @@ eql.execute("Hello, <%= strings.toUpper(name) %>!\n", "", "")
Hello, QLANG!
```

### eql.executeFile(source, output)
### eql.ExecuteFile(source, output)

执行 eql 模板文件。

* source: 为 eql 模板文件。
* output: 为输出文件,为 "" 表示输出到 stdout。

### eql.executeDir(vars, source, output)
### eql.ExecuteDir(vars, source, output)

执行 eql 模板目录。

Expand Down
4 changes: 2 additions & 2 deletions cmd/eql/eql_main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import (
"qlang.io/cl/interpreter"
"qlang.io/cl/qlang"
"qlang.io/exec"
"qlang.io/qlang/eqlang"
"qlang.io/qlang/qlang.all"
"qlang.io/lib/eqlang"
"qlang.io/lib/qlang.all"
)

// -----------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion cmd/eql/example.eql
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
package eql_test

import (
<%= eql.imports() %>
<%= eql.Imports() %>
"encoding/binary"
)

Expand Down
Loading

0 comments on commit c7631d9

Please sign in to comment.