diff options
| author | Charlie Stanton <charlie@shtanton.xyz> | 2023-04-19 13:58:13 +0100 | 
|---|---|---|
| committer | Charlie Stanton <charlie@shtanton.xyz> | 2023-04-19 13:58:13 +0100 | 
| commit | ca161b26e9b6a253837e5ec4e0cf318bd0ee7903 (patch) | |
| tree | c3863c145024fd1124943e1eab525230c3236aaa /subex | |
| parent | d3d17484012dc603ae326bec419cff990898e6a0 (diff) | |
| download | stred-go-ca161b26e9b6a253837e5ec4e0cf318bd0ee7903.tar | |
Adds the NOT operator
Diffstat (limited to 'subex')
| -rw-r--r-- | subex/arithmetic.go | 24 | ||||
| -rw-r--r-- | subex/parse.go | 2 | ||||
| -rw-r--r-- | subex/subexast.go | 15 | 
3 files changed, 41 insertions, 0 deletions
| diff --git a/subex/arithmetic.go b/subex/arithmetic.go index 4404a1c..52f576d 100644 --- a/subex/arithmetic.go +++ b/subex/arithmetic.go @@ -152,3 +152,27 @@ func reciprocalValues(atoms []walk.Atom) ([]walk.Atom, error) {  	}  	return reciprocals, nil  } + +// If all are castable to booleans, NOTs all and returns them +// Else errors +func notValues(atoms []walk.Atom) (notted []walk.Atom, err error) { +	values, err := walk.MemoryCompound(atoms) +	if err != nil { +		return nil, err +	} +	for _, value := range values { +		switch v := value.(type) { +			case walk.ValueNull: +				notted = append(notted, walk.ValueBool(true)) +			case walk.ValueBool: +				notted = append(notted, walk.ValueBool(!v)) +			case walk.ValueNumber: +				notted = append(notted, walk.ValueBool(v == 0)) +			case walk.ValueString: +				notted = append(notted, walk.ValueBool(len(v) == 0)) +			default: +				return nil, errors.New("Tried to NOT non-boolean") +		} +	} +	return notted, nil +} diff --git a/subex/parse.go b/subex/parse.go index f5316c9..8b3a553 100644 --- a/subex/parse.go +++ b/subex/parse.go @@ -242,6 +242,8 @@ func parseSubex(l *RuneReader, minPower int) SubexAST {  				lhs = SubexASTNegate {lhs}  			case r == '/' && minPower <= 8:  				lhs = SubexASTReciprocal {lhs} +			case r == '!' && minPower <= 8: +				lhs = SubexASTNot {lhs}  			case r == '$' && minPower <= 8:  				slot := l.next()  				if slot == eof { diff --git a/subex/subexast.go b/subex/subexast.go index 78c9aff..fb16658 100644 --- a/subex/subexast.go +++ b/subex/subexast.go @@ -238,3 +238,18 @@ func (ast SubexASTReciprocal) compileWith(next SubexState) SubexState {  		}),  	}  } + +// Runs the content Subex and collects the output +// Maps over the values in the output, casting each to a boolean, notting each and then outputs them +// Rejects if it cannot cast to boolean +type SubexASTNot struct { +	content SubexAST +} +func (ast SubexASTNot) compileWith(next SubexState) SubexState { +	return &SubexCaptureBeginState { +		next: ast.content.compileWith(&SubexArithmeticEndState { +			next: next, +			calculate: notValues, +		}), +	} +} | 
