func TestSymbolResolveAll(t *testing.T) { var builtins = map[string]*ast.Stmt{ // Date "gmtdate": ast.NewDate(stdtime.Now(), "YYYYMMDD"), "bizdate": ast.NewDate(stdtime.Now().AddDate(0, 0, -1), "YYYYMMDD"), // Duration "year": ast.NewDurationExt(1, 0, 0), "month": ast.NewDurationExt(0, 1, 0), "day": ast.NewDurationExt(0, 0, 1), "hour": ast.NewDuration(stdtime.Hour), "minute": ast.NewDuration(stdtime.Minute), "second": ast.NewDuration(stdtime.Second), } src := "$res=$gmtdate-1*$day" ret, err := symbol.Resolve(src, builtins) if err != nil { t.Error(err) return } res := ret[0] check := ast.NewLeftID("res", ast.NewDate(stdtime.Now().AddDate(0, 0, -1), "YYYYMMDD")) if !res.Equals(check) { t.Error(fmt.Errorf("%s=%d", src, res.Value.(string))) return } //fmt.Println(res) }
func TestEvalTimes(t *testing.T) { src := "$res=3*9" //fmt.Printf("src: %s\n", src) ret := getTestEvalResult(src, t) if ret == nil { return } res := ret[0] check := ast.NewLeftID("res", ast.NewInt(27)) if !res.Equals(check) { t.Error(fmt.Errorf("%s => %d", src, res.Value.(int))) return } //fmt.Printf("res: %v\n", res) }
func TestEvalAddFloat(t *testing.T) { src := "$res=1.1+2.2" //fmt.Printf("src: %s\n", src) ret := getTestEvalResult(src, t) if ret == nil { return } res := ret[0] check := ast.NewLeftID("res", ast.NewFloat(3.3)) if !res.Equals(check) { t.Error(fmt.Errorf("%s => %v", src, res.Value)) return } //fmt.Printf("res: %v\n", res) }
func TestEvalDate(t *testing.T) { src := "$res=${date:YYYYMMDD}" //fmt.Printf("src: %s\n", src) ret := getTestEvalResult(src, t) if ret == nil { return } res := ret[0] check := ast.NewLeftID("res", ast.NewDate(stdtime.Now(), "YYYYMMDD")) if !res.Equals(check) { t.Error(fmt.Errorf("%v=%v", res.Value, check.Value)) return } //fmt.Printf("res: %v\n", res) }
func TestEvalEnv(t *testing.T) { src := "$res=${env:HADOOP_HOME}" os.Setenv("HADOOP_HOME", "/hadoop_home") //fmt.Printf("src: %s\n", src) ret := getTestEvalResult(src, t) if ret == nil { return } res := ret[0] check := ast.NewLeftID("res", ast.NewString("/hadoop_home")) if !res.Equals(check) { t.Error(fmt.Errorf("%v=%v", res.Value, check.Value)) return } //fmt.Printf("res: %v\n", res) }
func (this *Eval) Evaluate(stmtlist []*ast.Stmt, builtins map[string]*ast.Stmt) ([]*ast.Stmt, error) { if builtins != nil { this.Builtins = builtins } else { this.Builtins = make(map[string]*ast.Stmt) } list := []*ast.Stmt{} for _, stmt := range stmtlist { if s, err := this.evalStmt(stmt); err != nil { return nil, err } else { list = append(list, s) } } for k, v := range this.Builtins { list = append(list, ast.NewLeftID(k, v)) } return list, nil }
func (this *Eval) evalOperator(op1 *ast.Stmt, op2 *ast.Stmt, opstr string) (*ast.Stmt, error) { if op1.Type == ast.Int && op2.Type == ast.Int { var res int a := op1.Prop["value"].(int) b := op2.Prop["value"].(int) switch opstr { case "+": res = a + b case "-": res = a - b case "*": res = a * b case "/": res = a / b default: return nil, fmt.Errorf("invalid operator between Integers: %s", opstr) } return ast.NewInt(res), nil } if (op1.Type == ast.Float || op2.Type == ast.Int) && (op1.Type == ast.Int || op2.Type == ast.Float) { var res float64 var a float64 var b float64 var err error a, err = strconv.ParseFloat(op1.Value.(string), 64) if err != nil { return nil, fmt.Errorf("invalid float: %s", op1.Value) } b, err = strconv.ParseFloat(op2.Value.(string), 64) if err != nil { return nil, fmt.Errorf("invalid float: %s", op2.Value) } switch opstr { case "+": res = a + b case "-": res = a - b case "*": res = a * b case "/": res = a / b default: return nil, fmt.Errorf("invalid operator between Integers: %s", opstr) } return ast.NewFloat(res), nil } if op1.Type == ast.LeftID { if opstr != "=" { return nil, fmt.Errorf("invalid operator for LeftID: %s", opstr) } return ast.NewLeftID(op1.Value.(string), op2), nil } if op1.Type == ast.Date && op2.Type == ast.Duration { var ret stdtime.Time old := op1.Prop["time"].(stdtime.Time) duration := op2.Prop["time"].(stdtime.Duration) switch opstr { case "+": ret = old.Add(duration) case "-": ret = old.Add(-1 * duration) default: return nil, fmt.Errorf("invalid operator between Date and Duration: %s", opstr) } return ast.NewDate(ret, op1.Prop["format"].(string)), nil } if op1.Type == ast.Date && op2.Type == ast.DurationExt { var ret stdtime.Time old := op1.Prop["time"].(stdtime.Time) year := op2.Prop["year"].(int) month := op2.Prop["month"].(int) day := op2.Prop["day"].(int) switch opstr { case "+": ret = old.AddDate(year, month, day) case "-": ret = old.AddDate(-1*year, -1*month, -1*day) default: return nil, fmt.Errorf("invalid operator between Date and Duration: %s", opstr) } return ast.NewDate(ret, op1.Prop["format"].(string)), nil } if op1.Type == ast.Int && op2.Type == ast.Duration { if opstr != "*" { return nil, fmt.Errorf("invalid operator between Int and Duration: %s", opstr) } n := op1.Prop["value"].(int) return ast.NewDuration(stdtime.Duration(n) * op2.Prop["time"].(stdtime.Duration)), nil } if op1.Type == ast.Int && op2.Type == ast.DurationExt { if opstr != "*" { return nil, fmt.Errorf("invalid operator between Int and Duration: %s", opstr) } n := op1.Prop["value"].(int) return ast.NewDurationExt( n*op2.Prop["year"].(int), n*op2.Prop["month"].(int), n*op2.Prop["day"].(int)), nil } return nil, fmt.Errorf("invalid operation pair type: %s and %s", op1.Type, op2.Type) }
Id: "StmtList", NTType: 1, Index: 2, NumSymbols: 3, ReduceFunc: func(X []Attrib) (Attrib, error) { return ast.AppendStmtList(X[0].([]*ast.Stmt), X[2].(*ast.Stmt)), nil }, }, ProdTabEntry{ String: `Stmt : "$" id "=" Expr << ast.NewOperatorFromParser(ast.NewLeftID(string(X[1].(*token.Token).Lit)), "=", X[3].(*ast.Stmt)) >>`, Id: "Stmt", NTType: 2, Index: 3, NumSymbols: 4, ReduceFunc: func(X []Attrib) (Attrib, error) { return ast.NewOperatorFromParser(ast.NewLeftID(string(X[1].(*token.Token).Lit)), "=", X[3].(*ast.Stmt)) }, }, ProdTabEntry{ String: `Expr : Expr "+" Term << ast.NewOperatorFromParser(X[0].(*ast.Stmt), "+", X[2].(*ast.Stmt)) >>`, Id: "Expr", NTType: 3, Index: 4, NumSymbols: 3, ReduceFunc: func(X []Attrib) (Attrib, error) { return ast.NewOperatorFromParser(X[0].(*ast.Stmt), "+", X[2].(*ast.Stmt)) }, }, ProdTabEntry{ String: `Expr : Expr "-" Term << ast.NewOperatorFromParser(X[0].(*ast.Stmt), "-", X[2].(*ast.Stmt)) >>`, Id: "Expr",