Introduce Bool type and Value.Bool method.

The "if" builtin now uses the Value.Bool method to determine trueness.
This commit is contained in:
Cheer Xiao 2015-01-21 23:50:40 +01:00
parent 27a625387e
commit 65e1e19846
3 changed files with 63 additions and 2 deletions

View File

@ -159,7 +159,7 @@ func each(ev *Evaluator, args []Value) Exitus {
} }
// if takes a sequence of values and a trailing nullary closure. If all of the // if takes a sequence of values and a trailing nullary closure. If all of the
// values are true (= are empty strings), the closure is executed. // values are true, the closure is executed.
func ifFn(ev *Evaluator, args []Value) Exitus { func ifFn(ev *Evaluator, args []Value) Exitus {
if len(args) == 0 { if len(args) == 0 {
return argsError return argsError
@ -170,7 +170,7 @@ func ifFn(ev *Evaluator, args []Value) Exitus {
return argsError return argsError
} else { } else {
for _, a := range args[:len(args)-1] { for _, a := range args[:len(args)-1] {
if a.String() != "" { if !a.Bool() {
return success return success
} }
} }

View File

@ -52,6 +52,8 @@ func NewEvaluator() *Evaluator {
"env": valuePtr(env), "env": valuePtr(env),
"pid": valuePtr(pid), "pid": valuePtr(pid),
"success": valuePtr(success), "success": valuePtr(success),
"true": valuePtr(Bool(true)),
"false": valuePtr(Bool(false)),
} }
ev := &Evaluator{ ev := &Evaluator{
Compiler: NewCompiler(), Compiler: NewCompiler(),

View File

@ -40,6 +40,17 @@ func (st StringType) String() string {
return "string" return "string"
} }
type BoolType struct {
}
func (bt BoolType) Default() Value {
return Bool(true)
}
func (bt BoolType) String() string {
return "bool"
}
type ExitusType struct { type ExitusType struct {
} }
@ -87,6 +98,7 @@ func (ct ClosureType) String() string {
var typenames = map[string]Type{ var typenames = map[string]Type{
"string": StringType{}, "string": StringType{},
"exitus": ExitusType{}, "exitus": ExitusType{},
"bool": BoolType{},
"table": TableType{}, "table": TableType{},
"env": EnvType{}, "env": EnvType{},
"closure": ClosureType{}, "closure": ClosureType{},
@ -102,6 +114,7 @@ type Value interface {
Type() Type Type() Type
Repr() string Repr() string
String() string String() string
Bool() bool
} }
func valuePtr(v Value) *Value { func valuePtr(v Value) *Value {
@ -170,6 +183,36 @@ func (s String) String() string {
return string(s) return string(s)
} }
func (s String) Bool() bool {
return true
}
type Bool bool
func (b Bool) Type() Type {
return BoolType{}
}
func (b Bool) Repr() string {
if b {
return "$true"
} else {
return "$false"
}
}
func (b Bool) String() string {
if b {
return "true"
} else {
return "false"
}
}
func (b Bool) Bool() bool {
return bool(b)
}
type Exitus struct { type Exitus struct {
Success bool Success bool
Failure string Failure string
@ -201,6 +244,10 @@ func (e Exitus) String() string {
} }
} }
func (e Exitus) Bool() bool {
return e.Success
}
// Table is a list-dict hybrid. // Table is a list-dict hybrid.
// //
// TODO(xiaq): The dict part use string keys. It should use Value keys instead. // TODO(xiaq): The dict part use string keys. It should use Value keys instead.
@ -237,6 +284,10 @@ func (t *Table) String() string {
return t.Repr() return t.Repr()
} }
func (t *Table) Bool() bool {
return t.Bool()
}
func (t *Table) append(vs ...Value) { func (t *Table) append(vs ...Value) {
t.List = append(t.List, vs...) t.List = append(t.List, vs...)
} }
@ -287,6 +338,10 @@ func (e Env) String() string {
return e.Repr() return e.Repr()
} }
func (e Env) Bool() bool {
return true
}
// Closure is a closure. // Closure is a closure.
type Closure struct { type Closure struct {
ArgNames []string ArgNames []string
@ -310,6 +365,10 @@ func (c *Closure) String() string {
return c.Repr() return c.Repr()
} }
func (c *Closure) Bool() bool {
return true
}
func evalSubscript(ev *Evaluator, left, right Value, lp, rp parse.Pos) Value { func evalSubscript(ev *Evaluator, left, right Value, lp, rp parse.Pos) Value {
var ( var (
sub String sub String