boolean system

This commit is contained in:
Aidan 2020-06-28 20:06:55 -07:00
parent e7d25057f6
commit 89d6a1013b
No known key found for this signature in database
GPG key ID: 327711E983899316
5 changed files with 209 additions and 1 deletions

3
.gitignore vendored
View file

@ -14,3 +14,6 @@ print_ast
*~
*.swp
*.swo
# notes
*.txt*

View file

@ -30,7 +30,7 @@ func (t *Token) String() string {
case STRING:
return "\"" + t.Inner.(string) + "\""
case NUMBER:
case NUMBER, BOOL:
return t.Inner.(string)
case LIST:

View file

@ -28,6 +28,7 @@ const (
STRING Token_t = iota
NUMBER Token_t = iota
SYMBOL Token_t = iota
BOOL Token_t = iota
)
type Token struct {

155
stdlib/bool.go Normal file
View file

@ -0,0 +1,155 @@
/* SHS: Syntactically Homogeneous Shell
* Copyright (C) 2019 Aidan Hahn
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package stdlib
import (
"strconv"
"gitlab.com/whom/shs/log"
"gitlab.com/whom/shs/ast"
)
// lt, gt
func not(in *ast.Token, vt ast.VarTable, ft ast.FuncTable) *ast.Token {
if in.Tag != ast.BOOL {
log.Log(log.ERR, "non-bool argument to 'not'", "not")
return nil
}
out := "T"
if in.Inner.(string) == "T" {
out = "F"
}
return &ast.Token{Tag: ast.BOOL, Inner: out}
}
func eq(in *ast.Token, vt ast.VarTable, ft ast.FuncTable) *ast.Token {
out := "T"
second := in.Next
if in.Tag != second.Tag {
out = "F"
} else {
switch in.Tag {
case ast.LIST:
// returns true if difference found
var consume_list func(*ast.Token, *ast.Token) bool
consume_list = func(l *ast.Token, r *ast.Token) bool {
if (l == nil && r != nil) || (r == nil && l != nil) {
return true
}
if l.Tag != r.Tag {
return true
}
l_iter := l
r_iter := r
for l_iter != nil {
if r_iter == nil || l_iter.Tag != r_iter.Tag {
return true
}
if l_iter.Tag == ast.LIST {
diff := consume_list(l_iter.Inner.(*ast.Token),
r_iter.Inner.(*ast.Token))
if diff {
return true
}
} else {
if l_iter.Inner.(string) != r_iter.Inner.(string) {
return true
}
}
l_iter = l_iter.Next
r_iter = r_iter.Next
}
if r_iter != nil {
return true
} else {
return false
}
}
if consume_list(in.Inner.(*ast.Token), second.Inner.(*ast.Token)) {
out = "F"
}
case ast.NUMBER, ast.STRING, ast.BOOL:
if in.Inner.(string) != second.Inner.(string) {
out = "F"
}
}
}
return &ast.Token{Tag: ast.BOOL, Inner: out}
}
func lt(in *ast.Token, vt ast.VarTable, ft ast.FuncTable) *ast.Token {
out := "T"
second := in.Next
if in.Tag != ast.NUMBER || second.Tag != ast.NUMBER {
log.Log(log.ERR, "non-number argument to numeric boolean operator", ">/<=")
return nil
}
l, _ := strconv.ParseInt(in.Inner.(string), 10, 64)
r, _ := strconv.ParseInt(second.Inner.(string), 10, 64)
if l >= r {
out = "F"
}
return &ast.Token{Tag: ast.BOOL, Inner: out}
}
func gt(in *ast.Token, vt ast.VarTable, ft ast.FuncTable) *ast.Token {
out := "T"
second := in.Next
if in.Tag != ast.NUMBER || second.Tag != ast.NUMBER {
log.Log(log.ERR, "non-number argument to numeric boolean operator", ">/<=")
return nil
}
l, _ := strconv.ParseInt(in.Inner.(string), 10, 64)
r, _ := strconv.ParseInt(second.Inner.(string), 10, 64)
if l <= r {
out = "F"
}
return &ast.Token{Tag: ast.BOOL, Inner: out}
}
func ne(in *ast.Token, vt ast.VarTable, ft ast.FuncTable) *ast.Token {
return not(eq(in, vt, ft), vt, ft)
}
func gte(in *ast.Token, vt ast.VarTable, ft ast.FuncTable) *ast.Token {
return not(lt(in, vt, ft), vt, ft)
}
func lte(in *ast.Token, vt ast.VarTable, ft ast.FuncTable) *ast.Token {
return not(gt(in, vt, ft), vt, ft)
}

View file

@ -140,6 +140,55 @@ func GenFuncTable() ast.FuncTable {
},
*/
"eq": &ast.Function{
Function: eq,
Name: "==",
TimesCalled: 0,
Args: 2,
},
"ne": &ast.Function{
Function: ne,
Name: "!=",
TimesCalled: 0,
Args: 2,
},
"<": &ast.Function{
Function: lt,
Name: "<",
TimesCalled: 0,
Args: 2,
},
">": &ast.Function{
Function: gt,
Name: ">",
TimesCalled: 0,
Args: 2,
},
"<=": &ast.Function{
Function: lte,
Name: "<=",
TimesCalled: 0,
Args: 2,
},
">=": &ast.Function{
Function: gte,
Name: ">=",
TimesCalled: 0,
Args: 2,
},
"!": &ast.Function{
Function: not,
Name: "!",
TimesCalled: 0,
Args: 1,
},
"jobs": &ast.Function{
Function: jobs,
Name: "list jobs",