From 8a11afb78f52e7f275f59ef6fdb177ef9b287aa4 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Sun, 17 May 2020 16:22:43 +0800 Subject: [PATCH] interpreter.Context --- tpl/interpreter.util/call.go | 15 ++++++++------- tpl/interpreter/interpreter.go | 19 +++++++++++++------ tpl/interpreter/interpreter_test.go | 15 +++++++++++---- tpl/qlang/cl/ctrl.go | 3 ++- 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/tpl/interpreter.util/call.go b/tpl/interpreter.util/call.go index fce24aa..73edeb1 100644 --- a/tpl/interpreter.util/call.go +++ b/tpl/interpreter.util/call.go @@ -20,13 +20,6 @@ var ( // ----------------------------------------------------------------------------- -// Context represents the context of an interpreter. -type Context struct { - Src interface{} // []tpl.Token - Pos token.Pos - End token.Pos -} - // FileLine represents file name and line number. type FileLine struct { File string @@ -53,6 +46,14 @@ type Engine interface { Source(src interface{}) []byte } +// Context represents the context of an interpreter. +type Context struct { + Src interface{} // []tpl.Token + Pos token.Pos + End token.Pos + Engine Engine +} + // Call calls a fn. func Call(stk Stack, fn interface{}, arity int) error { tfn := reflect.TypeOf(fn) diff --git a/tpl/interpreter/interpreter.go b/tpl/interpreter/interpreter.go index 053ee25..0a4ed46 100644 --- a/tpl/interpreter/interpreter.go +++ b/tpl/interpreter/interpreter.go @@ -15,6 +15,7 @@ import ( var ( typeIntf = reflect.TypeOf((*interface{})(nil)).Elem() typeEng = reflect.TypeOf((*interpreter.Engine)(nil)).Elem() + typeCtx = reflect.TypeOf((*interpreter.Context)(nil)) zeroIntfVal = reflect.Zero(typeIntf) ) @@ -263,6 +264,8 @@ func New(ipt interpreter.Interface, options *Options) (p *Engine, err error) { args[1] = reflect.ValueOf(g.Len()) } else { switch targ1 { + case typeCtx: + args[1] = p.ctxValue(tokens) case typeIntf: if len(tokens) == 0 { // use nil as empty source args[1] = zeroIntfVal @@ -281,12 +284,7 @@ func New(ipt interpreter.Interface, options *Options) (p *Engine, err error) { } } if n == 3 { - ctx := &interpreter.Context{Src: tokens} - if len(tokens) > 0 { - ctx.Pos = tokens[0].Pos - ctx.End = tokens[len(tokens)-1].End() - } - args[2] = reflect.ValueOf(ctx) + args[2] = p.ctxValue(tokens) } ret := reflect.ValueOf(fn).Call(args) if len(ret) > 0 { @@ -321,6 +319,15 @@ func New(ipt interpreter.Interface, options *Options) (p *Engine, err error) { return } +func (p *Engine) ctxValue(tokens []tpl.Token) reflect.Value { + ctx := &interpreter.Context{Src: tokens, Engine: interpreter.Engine(p)} + if len(tokens) > 0 { + ctx.Pos = tokens[0].Pos + ctx.End = tokens[len(tokens)-1].End() + } + return reflect.ValueOf(ctx) +} + // Source returns the source text of src. func (p *Engine) Source(src interface{}) (text []byte) { if src == nil { diff --git a/tpl/interpreter/interpreter_test.go b/tpl/interpreter/interpreter_test.go index ae5367b..635969a 100644 --- a/tpl/interpreter/interpreter_test.go +++ b/tpl/interpreter/interpreter_test.go @@ -12,7 +12,7 @@ import ( // ----------------------------------------------------------------------------- const codeIf = ` -today = 3 +today = 5 if today == 1 { today = "Mon" @@ -20,9 +20,16 @@ if today == 1 { today = "Tue" } elif today == 3 { today = "Wed" +} else { + today = 0 + for i = 0; i < 10; i++ { + today = today + i + } } println(today) + +panic("haha") ` func TestIf(t *testing.T) { @@ -32,14 +39,14 @@ func TestIf(t *testing.T) { } err = lang.SafeEval(codeIf) - if err != nil { + if err != nil && err.Error() != "line 19: runtime error: haha" { t.Fatal(err) } v, _ := lang.Var("today") fmt.Println(v) - if v != "Wed" { - t.Fatal("MaxPrime ret:", v) + if v != 45 { + t.Fatal("ret:", v) } } diff --git a/tpl/qlang/cl/ctrl.go b/tpl/qlang/cl/ctrl.go index 875826a..bc39e31 100644 --- a/tpl/qlang/cl/ctrl.go +++ b/tpl/qlang/cl/ctrl.go @@ -44,9 +44,10 @@ func (p *Interpreter) And(e interpreter.Engine) { evalCode(e, p, "term3", bCode) } -func (p *Interpreter) If(e interpreter.Engine) { +func (p *Interpreter) If(ctx *interpreter.Context) { var elseCode interface{} + var e = ctx.Engine stk := p.stk elseArity := stk.popArity()