SHS/stdlib/stdlib.go

480 lines
12 KiB
Go
Raw Normal View History

2019-11-29 12:57:03 -08:00
/* 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/>.
*/
2020-06-21 11:11:57 -07:00
package stdlib
import (
"os"
2020-06-29 21:21:30 -07:00
"fmt"
2020-06-28 13:47:44 -07:00
"gitlab.com/whom/shs/ast"
"gitlab.com/whom/shs/util"
)
2020-07-19 14:53:27 -07:00
/* Makes a FuncTable from all functions in the stdlib
* add your function here if you are extending the standard library
*/
2020-06-21 11:11:57 -07:00
func GenFuncTable() ast.FuncTable {
var stdlib ast.FuncTable
stdlib = &map[string]*ast.Function{
2020-07-02 16:24:34 -07:00
"if": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: ShsIf,
2020-06-30 20:27:12 -07:00
Name: "if",
2020-08-21 17:37:54 -07:00
NumArgs: 3,
EvalLazy: true,
ArgLazy: true,
2020-06-30 20:27:12 -07:00
},
2020-07-02 16:24:34 -07:00
"while": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: ShsWhile,
2020-06-30 20:27:12 -07:00
Name: "while",
2020-08-21 17:37:54 -07:00
NumArgs: -1,
EvalLazy: true,
ArgLazy: true,
2020-06-30 20:27:12 -07:00
},
2020-07-18 10:44:18 -07:00
"progn": &ast.Function{
2020-07-19 14:37:20 -07:00
Function: ShsProgn,
2020-08-21 17:37:54 -07:00
Name: "shs_progn",
NumArgs: -1,
EvalLazy: true,
ArgLazy: true,
2020-07-18 10:44:18 -07:00
},
"func": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: DeclFunc,
Name: "decl_func",
Args: []ast.Token_t{
ast.STRING,
ast.LIST,
2020-08-21 17:37:54 -07:00
ast.LIST,
},
2020-08-21 17:37:54 -07:00
EvalLazy: true,
},
2020-07-24 19:58:09 -07:00
"len": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Len,
Name: "len",
NumArgs: 1,
ArgLazy: true,
2020-07-24 19:58:09 -07:00
},
"head": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Head,
2020-07-24 19:58:09 -07:00
Name: "head",
2020-08-21 17:37:54 -07:00
Args: []ast.Token_t{
ast.LIST,
},
2020-07-24 19:58:09 -07:00
},
"tail": &ast.Function{
Function: Tail,
2020-08-21 17:37:54 -07:00
Name: "tail",
Args: []ast.Token_t{
ast.LIST,
},
2020-07-24 19:58:09 -07:00
},
2020-07-24 20:32:08 -07:00
"slice": &ast.Function{
Function: Slice,
2020-08-21 17:37:54 -07:00
Name: "slice",
Args: []ast.Token_t{
ast.NUMBER,
ast.NUMBER,
2020-08-21 17:37:54 -07:00
ast.LIST,
},
2020-07-24 20:32:08 -07:00
},
2020-07-24 19:58:09 -07:00
2020-07-03 16:27:02 -07:00
"export": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Export,
Name: "export",
EvalLazy: true,
2020-08-22 12:37:06 -07:00
ArgLazy: true,
NumArgs: 2,
2020-07-03 16:27:02 -07:00
},
"input": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Input,
Name: "input",
Args: []ast.Token_t{
ast.STRING,
},
2020-07-02 16:24:34 -07:00
},
"load": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Load,
Name: "load",
Args: []ast.Token_t{
ast.STRING,
},
},
2020-07-18 00:22:43 -07:00
"bool": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: BoolCast,
Name: "bool",
Args: []ast.Token_t{
ast.STRING,
},
2020-07-18 00:22:43 -07:00
},
"string": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: StrCast,
Name: "string",
NumArgs: 1,
ArgLazy: true,
2020-07-18 00:22:43 -07:00
},
"number": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: NumCast,
Name: "number",
Args: []ast.Token_t{
ast.NUMBER,
},
2020-07-18 00:22:43 -07:00
},
"...": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Expand,
Name: "...",
Args: []ast.Token_t{
ast.LIST,
},
2020-06-21 12:29:20 -07:00
},
"append": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: L_append,
Name: "append",
NumArgs: -1,
ArgLazy: true,
},
2020-06-26 20:17:45 -07:00
2020-08-20 23:39:57 -07:00
"join": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Join,
Name: "join",
Args: []ast.Token_t{
ast.STRING,
2020-08-21 17:37:54 -07:00
ast.LIST,
},
2020-08-20 23:39:57 -07:00
},
2020-08-14 15:59:38 -07:00
"split": &ast.Function{
Function: Split,
2020-08-21 17:37:54 -07:00
Name: "split",
Args: []ast.Token_t{
ast.STRING,
ast.STRING,
},
2020-08-14 15:59:38 -07:00
},
2020-08-21 00:14:31 -07:00
"substr": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Substr,
Name: "substr",
Args: []ast.Token_t{
ast.NUMBER,
ast.NUMBER,
2020-08-21 17:37:54 -07:00
ast.STRING,
},
2020-08-21 00:14:31 -07:00
},
2020-06-27 21:27:33 -07:00
"exit": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: ExitShell,
Name: "exit",
Args: []ast.Token_t{},
2020-06-27 21:27:33 -07:00
},
"eq": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Eq,
Name: "==",
NumArgs: 2,
ArgLazy: true,
},
"ne": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Ne,
Name: "!=",
NumArgs: 2,
ArgLazy: true,
},
"<": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Lt,
Name: "<",
Args: []ast.Token_t{
ast.NUMBER,
ast.NUMBER,
},
},
">": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Gt,
Name: ">",
Args: []ast.Token_t{
ast.NUMBER,
ast.NUMBER,
},
},
"<=": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Lte,
Name: "<=",
Args: []ast.Token_t{
ast.NUMBER,
ast.NUMBER,
},
},
">=": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Gte,
Name: ">=",
Args: []ast.Token_t{
ast.NUMBER,
ast.NUMBER,
},
},
"!": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Not,
Name: "!",
Args: []ast.Token_t{
ast.BOOL,
},
},
2020-06-29 12:51:41 -07:00
"+": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Add,
Name: "add",
NumArgs: -1,
ArgLazy: true,
2020-06-29 12:51:41 -07:00
},
"-": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Sub,
Name: "sub",
NumArgs: -1,
ArgLazy: true,
2020-06-29 12:51:41 -07:00
},
"*": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Mult,
2020-06-29 12:51:41 -07:00
Name: "mult",
2020-08-21 17:37:54 -07:00
NumArgs: -1,
ArgLazy: true,
2020-06-29 12:51:41 -07:00
},
"/": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Div,
Name: "div",
NumArgs: -1,
ArgLazy: true,
2020-06-29 12:51:41 -07:00
},
2020-06-29 16:58:43 -07:00
"cd": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Cd,
Name: "changedir",
Args: []ast.Token_t{
ast.STRING,
},
2020-06-29 16:58:43 -07:00
},
2020-06-29 17:06:27 -07:00
"concat": &ast.Function{
2020-07-19 14:37:20 -07:00
Function: Concat,
2020-08-21 17:37:54 -07:00
Name: "concatenate",
NumArgs: -1,
ArgLazy: true,
2020-06-29 17:06:27 -07:00
},
"print": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: PrintStr,
Name: "print",
Args: []ast.Token_t{
ast.STRING,
},
2020-06-29 17:06:27 -07:00
},
"l": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Call,
Name: "call",
2020-08-21 17:37:54 -07:00
NumArgs: -1,
ArgLazy: true,
SymLazy: true,
},
"bg": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Bgcall,
Name: "background call",
NumArgs: -1,
ArgLazy: true,
SymLazy: true,
},
"fg": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Fg,
Name: "foreground",
Args: []ast.Token_t{
ast.NUMBER,
},
},
"$": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: ReadCmd,
Name: "read cmd",
NumArgs: -1,
ArgLazy: true,
SymLazy: true,
},
"?": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: GetExit,
Name: "get exit code",
Args: []ast.Token_t{},
},
/*
USE NATIVE KILL COMMAND.
"kill": &ast.Function{
Function: kill,
Name: "kill job",
Args: 1,
},
*/
"jobs": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Jobs,
Name: "list jobs",
Args: []ast.Token_t{},
},
2020-06-29 21:21:30 -07:00
"info": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: ShInfo,
Name: "Shell Info",
Args: []ast.Token_t{
ast.SYMBOL,
},
2020-06-29 21:21:30 -07:00
},
2020-07-02 19:35:22 -07:00
"fexists": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Fexists,
Name: "file exists",
Args: []ast.Token_t{
ast.STRING,
},
2020-07-02 19:35:22 -07:00
},
"fread": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Fread,
Name: "read file",
Args: []ast.Token_t{
ast.STRING,
},
2020-07-02 19:35:22 -07:00
},
"fwrite": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Fwrite,
Name: "write file",
Args: []ast.Token_t{
ast.STRING,
ast.STRING,
},
2020-07-02 19:35:22 -07:00
},
"fappend": &ast.Function{
2020-08-21 17:37:54 -07:00
Function: Fappend,
Name: "append to file",
Args: []ast.Token_t{
ast.STRING,
ast.STRING,
},
2020-07-02 19:35:22 -07:00
},
2020-06-21 12:29:20 -07:00
}
2020-06-21 11:11:57 -07:00
return stdlib
}
2020-06-27 21:27:33 -07:00
2020-07-19 14:37:20 -07:00
/* takes no args
* exits shell when called
*
* Example: (exit)
*/
func ExitShell(in *ast.Token, vt ast.VarTable, ft ast.FuncTable) *ast.Token {
2020-06-27 21:27:33 -07:00
os.Exit(0)
return nil // I hope execution doesnt get here
}
2020-06-29 21:21:30 -07:00
2020-07-19 14:37:20 -07:00
/* takes one arg, doesnt evaluate it
* returns type or metadata
*
* Example: (info append)
*/
func ShInfo(in *ast.Token, vt ast.VarTable, ft ast.FuncTable) *ast.Token {
2020-08-21 17:37:54 -07:00
repr := ast.GetVar(in.Value(), vt)
if repr != nil {
fmt.Printf("VARIABLE\nTYPE: %s\nVALUE: %s\n", ast.GetTagAsStr(repr.Tag), repr.Value())
return nil
}
2020-06-29 21:21:30 -07:00
2020-08-21 17:37:54 -07:00
funct := ast.GetFunction(in.Value(), ft)
if funct != nil {
fmt.Printf("FUNCTION\nNAME: %s\nTIMES CALLED: %s\n\n", funct.Name, funct.TimesCalled)
if funct.ArgLazy {
fmt.Printf("function does not evaluate args by type\nARG COUNT: %s\n", funct.NumArgs)
} else {
fmt.Printf("function evaluates args by type\nARGS: ")
for _, i := range(funct.Args) {
fmt.Printf(ast.GetTagAsStr(i))
}
2020-06-29 21:21:30 -07:00
}
2020-08-21 17:37:54 -07:00
fmt.Printf("SYMLAZY: %t\n", funct.SymLazy)
fmt.Printf("(can undefined symbols be passed in)\n")
fmt.Printf("EVALLAZY: %t\n", funct.EvalLazy)
fmt.Printf("(are all forms in evaluated before function call)\n")
return nil
2020-06-29 21:21:30 -07:00
}
2020-08-21 17:37:54 -07:00
fmt.Printf("UNKNOWN SYMBOL\n")
2020-06-29 21:21:30 -07:00
return nil
}
2020-06-30 20:27:12 -07:00
2020-07-19 14:37:20 -07:00
/* Takes 1 arg, uses it as a prompt
* errs if prompt is not a string or number
* gets a line from stdin
* returns it as a string
*
* Example: (print (input))
*/
func Input(in *ast.Token, vt ast.VarTable, ft ast.FuncTable) *ast.Token {
2020-07-02 16:24:34 -07:00
prompt := in.Value()
var output string
fmt.Printf(prompt)
fmt.Scanln(&output)
ret := &ast.Token{Tag: ast.STRING}
ret.Set(output)
return ret
}
2020-07-19 14:37:20 -07:00
/* Takes 1 arg, returns nil
* if arg is a valid existing file than load will execute it as a script
*
* Example: (load "myscript.shs")
*/
func Load(in *ast.Token, vt ast.VarTable, ft ast.FuncTable) *ast.Token {
bp := in.Value()
bp = AbsPath(bp)
util.LoadScript(bp, vt, ft)
return nil
}