Skip to content

Commit

Permalink
Merge pull request #128 from qiniu/develop
Browse files Browse the repository at this point in the history
Release v3.1.00
  • Loading branch information
xushiwei committed Nov 5, 2016
2 parents e36f492 + e95bf77 commit 65b3e8d
Show file tree
Hide file tree
Showing 11 changed files with 152 additions and 130 deletions.
29 changes: 14 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,6 @@ Q Language - A script language for Go
* 作为编译原理的教学语言。由于 qlang 的 Compiler 代码极短,便于阅读和理解,非常方便教学实践之用。


## 不兼容调整

qlang.v3 在 [qlang.v2](https://github.com/qiniu/qlang/tree/qlang.v2) 基础上,有如下不兼容调整:

1. exec.Context: Var(name) 改名为 GetVar(name);
2. 采用 vendor 机制,放弃手工在包名上带上版本号(这意味着我们不再支持 go1.4 及以下版本);
3. 目录结构调整:
- 语言规范:qlang.io/qlang.spec.v1 => qlang.io/spec
- 编译器:qlang.io/qlang.v2/qlang => qlang.io/cl/qlang
- 运行时:qlang.io/exec.v2 => qlang.io/exec
- 可执行程序:qlang.io/app/* => qlang.io/cmd/*


## 快速入门

### 在您的 Go 代码中整合 qlang
Expand Down Expand Up @@ -104,6 +91,20 @@ QLANG_DUMPCODE=1 qlang
* [Q 语言手册](README_QL.md): 这里有语言特性的详细介绍。
* [Qlang Tutorials](tutorial): 这里是一些 qlang 的样例代码,供您学习 qlang 时参考。


## 不兼容调整

qlang.v3 在 [qlang.v2](https://github.com/qiniu/qlang/tree/qlang.v2) 基础上,有如下不兼容调整:

1. exec.Context: Var(name) 改名为 GetVar(name);
2. 采用 vendor 机制,放弃手工在包名上带上版本号(这意味着我们不再支持 go1.4 及以下版本);
3. 目录结构调整:
- 语言规范:qlang.io/qlang.spec.v1 => qlang.io/spec
- 编译器:qlang.io/qlang.v2/qlang => qlang.io/cl/qlang
- 运行时:qlang.io/exec.v2 => qlang.io/exec
- 可执行程序:qlang.io/app/* => qlang.io/cmd/*


## 下载

### 发行版本
Expand All @@ -119,9 +120,7 @@ go get -u -insecure qlang.io/qlang
或者在 src 目录执行如下命令:

```
mkdir qiniupkg.com
git clone https://github.com/qiniu/qlang.git qlang.io
git clone https://github.com/qiniu/text.git qiniupkg.com/text
```

## 社区资源
Expand Down
41 changes: 21 additions & 20 deletions cl/interpreter/interpret2.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,29 +49,29 @@ func lastWord(s string) string {
return ""
}

func call(ip *exec.Object, name string) interface{} {
func call(estk *exec.Stack, ip *exec.Object, name string) interface{} {

if fn, ok := ip.Cls.Fns[name]; ok {
return fn.Call(ip)
return fn.Call(estk, ip)
}
panic("method not found: " + name)
}

func callN(ip *exec.Object, name string, args ...interface{}) interface{} {
func callN(estk *exec.Stack, ip *exec.Object, name string, args ...interface{}) interface{} {

if fn, ok := ip.Cls.Fns[name]; ok {
args1 := make([]interface{}, 1, len(args)+1)
args1[0] = ip
return fn.Call(append(args1, args...)...)
return fn.Call(estk, append(args1, args...)...)
}
panic("method not found: " + name)
}

func callFn(stk *exec.Object, fn interface{}, arity int) {
func callFn(estk *exec.Stack, stk *exec.Object, fn interface{}, arity int) {

var in []reflect.Value
if arity > 0 {
ret := reflect.ValueOf(callN(stk, "popArgs", arity))
ret := reflect.ValueOf(callN(estk, stk, "popArgs", arity))
if ret.Kind() != reflect.Slice {
panic("method stack.popArgs doesn't return a slice")
}
Expand All @@ -84,17 +84,17 @@ func callFn(stk *exec.Object, fn interface{}, arity int) {
vfn := reflect.ValueOf(fn)
out := vfn.Call(in)
if len(out) == 0 {
callN(stk, "push", nil)
callN(estk, stk, "push", nil)
} else {
callN(stk, "push", out[0].Interface())
callN(estk, stk, "push", out[0].Interface())
}
}

func callVfn(stk *exec.Object, fn *exec.Function, arity int) {
func callVfn(estk *exec.Stack, stk *exec.Object, fn *exec.Function, arity int) {

v := callN(stk, "popArgs", arity)
v := callN(estk, stk, "popArgs", arity)
if args, ok := v.([]interface{}); ok {
callN(stk, "push", fn.Call(args...))
callN(estk, stk, "push", fn.Call(estk, args...))
return
}

Expand All @@ -107,7 +107,7 @@ func callVfn(stk *exec.Object, fn *exec.Function, arity int) {
for i := 0; i < n; i++ {
in[i] = ret.Index(i).Interface()
}
callN(stk, "push", fn.Call(in...))
callN(estk, stk, "push", fn.Call(estk, in...))
}

func New(ip interface{}, options *Options) (p *Engine, err error) {
Expand All @@ -125,7 +125,8 @@ func New(ip interface{}, options *Options) (p *Engine, err error) {
}
}()

p = newEngine(ip, options)
estk := exec.NewStack()
p = newEngine(estk, ip, options)
return
}

Expand Down Expand Up @@ -153,7 +154,7 @@ func (p *Engine) Eval(expr string) (err error) {
return p.Exec([]byte(expr), "")
}

func newEngine(ip1 interface{}, options *Options) (p *Engine) {
func newEngine(estk *exec.Stack, ip1 interface{}, options *Options) (p *Engine) {

if options == nil {
options = &optionsDef
Expand All @@ -165,13 +166,13 @@ func newEngine(ip1 interface{}, options *Options) (p *Engine) {
}

p = new(Engine)
vstk := call(ip, "stack")
vstk := call(estk, ip, "stack")
stk, ok := vstk.(*exec.Object)
if !ok {
panic("stack isn't an object")
}

vfntable := call(ip, "fntable")
vfntable := call(estk, ip, "fntable")
fntable, ok := vfntable.(map[string]interface{})
if !ok {
panic("fntable isn't a map[string]interface{} object")
Expand Down Expand Up @@ -220,7 +221,7 @@ func newEngine(ip1 interface{}, options *Options) (p *Engine) {
return
}
}
callFn(stk, fn, n)
callFn(estk, stk, fn, n)
}
return tpl.Action(g, action)
}
Expand Down Expand Up @@ -288,15 +289,15 @@ func newEngine(ip1 interface{}, options *Options) (p *Engine) {
}
}
}
vfn.Call(args...)
vfn.Call(estk, args...)
} else {
callVfn(stk, vfn, n)
callVfn(estk, stk, vfn, n)
}
}
return tpl.Action(g, action)
}

vgrammar := call(ip, "grammar")
vgrammar := call(estk, ip, "grammar")
grammar, ok := vgrammar.(string)
if !ok {
panic("grammar isn't a string object")
Expand Down
7 changes: 0 additions & 7 deletions cl/qlang/engine2.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,6 @@ func New() *Qlang {
return &Qlang{ctx, cl}
}

// NewEx returns a new qlang instance.
//
func NewEx(options ...*Options) (lang *Qlang, err error) {

return New(), nil
}

// SetLibs sets lib paths for searching modules.
//
func (p *Qlang) SetLibs(libs string) {
Expand Down
55 changes: 48 additions & 7 deletions cmd/qexport/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,28 @@ import (
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
)

func apipath(base string) string {
return filepath.Join(os.Getenv("GOROOT"), "api", base)
}

//pkg syscall (windows-386), const CERT_E_CN_NO_MATCH = 2148204815
var sym = regexp.MustCompile(`^pkg (\S+)\s?(.*)?, (?:(var|func|type|const)) ([A-Z]\w*)`)
var num = regexp.MustCompile(`^\-?[0-9]+$`)

type KeyType int

const (
Normal KeyType = 1
ConstInt64 KeyType = 2
ConstUnit64 KeyType = 3
)

type GoApi struct {
Keys map[string]bool
Keys map[string]KeyType
Ver string
}

Expand All @@ -25,7 +36,7 @@ func LoadApi(ver string) (*GoApi, error) {
return nil, err
}
sc := bufio.NewScanner(f)
keys := make(map[string]bool)
keys := make(map[string]KeyType)
for sc.Scan() {
l := sc.Text()
has := func(v string) bool { return strings.Contains(l, v) }
Expand All @@ -38,20 +49,38 @@ func LoadApi(ver string) (*GoApi, error) {
// 3 var|func|type|const
// 4 name
key := m[1] + "." + m[4]
keys[key] = true
if _, ok := keys[key]; ok {
continue
}
keys[key] = Normal
if m[3] == "const" {
if pos := strings.LastIndex(l, "="); pos != -1 {
value := strings.TrimSpace(l[pos+1:])
if num.MatchString(value) {
_, err := strconv.ParseInt(l[pos+2:], 10, 32)
if err != nil {
if value[0] == '-' {
keys[key] = ConstInt64
} else {
keys[key] = ConstUnit64
}
}
}
}
}
}
}
return &GoApi{Ver: ver, Keys: keys}, nil
}

type ApiCheck struct {
Base map[string]bool
Base map[string]KeyType
Apis []*GoApi
}

func NewApiCheck() *ApiCheck {
ac := &ApiCheck{}
ac.Base = make(map[string]bool)
ac.Base = make(map[string]KeyType)
return ac
}

Expand All @@ -75,7 +104,7 @@ func (ac *ApiCheck) LoadApi(vers ...string) error {
return err
}
for k, _ := range api.Keys {
if ac.Base[k] {
if _, ok := ac.Base[k]; ok {
delete(api.Keys, k)
}
}
Expand All @@ -86,7 +115,7 @@ func (ac *ApiCheck) LoadApi(vers ...string) error {

func (ac *ApiCheck) FincApis(name string) (vers []string) {
for _, api := range ac.Apis {
if api.Keys[name] {
if _, ok := api.Keys[name]; ok {
vers = append(vers, api.Ver)
}
}
Expand All @@ -99,3 +128,15 @@ func (ac *ApiCheck) ApiVers() (vers []string) {
}
return
}

func (ac *ApiCheck) CheckConstType(name string) KeyType {
if typ, ok := ac.Base[name]; ok {
return typ
}
for _, api := range ac.Apis {
if typ, ok := api.Keys[name]; ok {
return typ
}
}
return Normal
}
15 changes: 0 additions & 15 deletions cmd/qexport/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,35 +10,20 @@ import (
// overridden by the -contexts flag.
var contexts = []*build.Context{
{GOOS: "linux", GOARCH: "386", CgoEnabled: true},
{GOOS: "linux", GOARCH: "386"},
{GOOS: "linux", GOARCH: "amd64", CgoEnabled: true},
{GOOS: "linux", GOARCH: "amd64"},
{GOOS: "linux", GOARCH: "arm", CgoEnabled: true},
{GOOS: "linux", GOARCH: "arm"},
{GOOS: "darwin", GOARCH: "386", CgoEnabled: true},
{GOOS: "darwin", GOARCH: "386"},
{GOOS: "darwin", GOARCH: "amd64", CgoEnabled: true},
{GOOS: "darwin", GOARCH: "amd64"},
{GOOS: "windows", GOARCH: "amd64", CgoEnabled: true},
{GOOS: "windows", GOARCH: "amd64"},
{GOOS: "windows", GOARCH: "386", CgoEnabled: true},
{GOOS: "windows", GOARCH: "386"},
{GOOS: "freebsd", GOARCH: "386", CgoEnabled: true},
{GOOS: "freebsd", GOARCH: "386"},
{GOOS: "freebsd", GOARCH: "amd64", CgoEnabled: true},
{GOOS: "freebsd", GOARCH: "amd64"},
{GOOS: "freebsd", GOARCH: "arm", CgoEnabled: true},
{GOOS: "freebsd", GOARCH: "arm"},
{GOOS: "netbsd", GOARCH: "386", CgoEnabled: true},
{GOOS: "netbsd", GOARCH: "386"},
{GOOS: "netbsd", GOARCH: "amd64", CgoEnabled: true},
{GOOS: "netbsd", GOARCH: "amd64"},
{GOOS: "netbsd", GOARCH: "arm", CgoEnabled: true},
{GOOS: "netbsd", GOARCH: "arm"},
{GOOS: "openbsd", GOARCH: "386", CgoEnabled: true},
{GOOS: "openbsd", GOARCH: "386"},
{GOOS: "openbsd", GOARCH: "amd64", CgoEnabled: true},
{GOOS: "openbsd", GOARCH: "amd64"},
}

func contextName(c *build.Context) string {
Expand Down
Loading

0 comments on commit 65b3e8d

Please sign in to comment.