Adds basic Makefile and bumps version number
This commit is contained in:
parent
c50929a6d4
commit
0dcafe95b0
|
@ -0,0 +1,25 @@
|
|||
GOCMD := go
|
||||
BINARY := felise
|
||||
PREFIX := /usr/local
|
||||
EXEC_PREFIX := ${PREFIX}
|
||||
BINDIR := ${EXEC_PREFIX}/bin
|
||||
DATAROOTDIR := ${PREFIX}/share
|
||||
MANDIR := ${DATAROOTDIR}/man
|
||||
MAN1DIR := ${MANDIR}/man1
|
||||
|
||||
|
||||
.PHONY: build
|
||||
build:
|
||||
${GOCMD} build -o ${BINARY}
|
||||
|
||||
.PHONY: install
|
||||
install: install-bin clean
|
||||
|
||||
.PHONY: install-bin
|
||||
install-bin:
|
||||
install -d ${DESTDIR}${BINDIR}
|
||||
install -m 0755 ./${BINARY} ${DESTDIR}${BINDIR}
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
${GOCMD} clean
|
4
go.mod
4
go.mod
|
@ -5,6 +5,6 @@ go 1.20
|
|||
require github.com/peterh/liner v1.2.2
|
||||
|
||||
require (
|
||||
github.com/mattn/go-runewidth v0.0.3 // indirect
|
||||
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.3 // indirect
|
||||
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1 // indirect
|
||||
)
|
||||
|
|
284
main.go
284
main.go
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
_
|
||||
|, _ |. __ _
|
||||
_
|
||||
|, _ |. __ _
|
||||
| (/,||_) (/,
|
||||
|
||||
Copyright (C) 2023 Brian Evans (aka sloum). All rights reserved.
|
||||
|
@ -17,20 +17,20 @@ https://www.floodgap.com/software/ffsl/license.html
|
|||
package main
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
_ "embed"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"strings"
|
||||
|
||||
ln "github.com/peterh/liner"
|
||||
ln "github.com/peterh/liner"
|
||||
)
|
||||
|
||||
const (
|
||||
version float64 = 0.2
|
||||
logo string = ` _
|
||||
|, _ |. __ _
|
||||
version float64 = 0.3
|
||||
logo string = ` _
|
||||
|, _ |. __ _
|
||||
| (/,||_) (/,`
|
||||
)
|
||||
|
||||
|
@ -39,16 +39,16 @@ var initialTerm ln.ModeApplier = nil
|
|||
var linerTerm ln.ModeApplier = nil
|
||||
var flagArgs []string
|
||||
var completions = []string{
|
||||
"var!", "set!", "scoped-var!", "scoped-set!", "proc", "proc!", "length",
|
||||
"dup", "drop", "over", "swap", "cast", "type", "while", "return",
|
||||
"dowhile", "if", "else", "and", "or", "stackdump", "clearstack",
|
||||
"->", "<-", "=>", "->!", "=>!", "append", "append!", "list-get",
|
||||
"list-set", "list-set!", "split", "join", "file-write", "file-remove",
|
||||
"file-exists?", "file-read", "docstring!", "input", "re-match?",
|
||||
"re-find", "re-replace", "slice", "stackdepth", "net-get", "try", "throw",
|
||||
"catch", "import", "rot", "each!", "filter!", "INT", "STRING", "FLOAT",
|
||||
"var!", "set!", "scoped-var!", "scoped-set!", "proc", "proc!", "length",
|
||||
"dup", "drop", "over", "swap", "cast", "type", "while", "return",
|
||||
"dowhile", "if", "else", "and", "or", "stackdump", "clearstack",
|
||||
"->", "<-", "=>", "->!", "=>!", "append", "append!", "list-get",
|
||||
"list-set", "list-set!", "split", "join", "file-write", "file-remove",
|
||||
"file-exists?", "file-read", "docstring!", "input", "re-match?",
|
||||
"re-find", "re-replace", "slice", "stackdepth", "net-get", "try", "throw",
|
||||
"catch", "import", "rot", "each!", "filter!", "INT", "STRING", "FLOAT",
|
||||
"LIST", "BOOL", "words",
|
||||
}
|
||||
}
|
||||
|
||||
//go:embed lib/std.fe
|
||||
var stdImport string
|
||||
|
@ -66,150 +66,150 @@ var pathsImport string
|
|||
var stringsImport string
|
||||
|
||||
func prompt(l *ln.State, cont bool) string {
|
||||
p := "> "
|
||||
p := "> "
|
||||
|
||||
if cont {
|
||||
p = "+ "
|
||||
}
|
||||
val, err := l.Prompt(p)
|
||||
if err == ln.ErrPromptAborted {
|
||||
return ""
|
||||
}
|
||||
l.AppendHistory(val)
|
||||
return val
|
||||
if cont {
|
||||
p = "+ "
|
||||
}
|
||||
val, err := l.Prompt(p)
|
||||
if err == ln.ErrPromptAborted {
|
||||
return ""
|
||||
}
|
||||
l.AppendHistory(val)
|
||||
return val
|
||||
}
|
||||
|
||||
func VersionString() string {
|
||||
return fmt.Sprintf("%.2f\n", version)
|
||||
return fmt.Sprintf("%.2f\n", version)
|
||||
}
|
||||
|
||||
func loadStdLib(en *env) error {
|
||||
err := lexParseInterpret(stdImport, en, "std")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
en.imports["std"] = true
|
||||
return nil
|
||||
err := lexParseInterpret(stdImport, en, "std")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
en.imports["std"] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func repl() {
|
||||
fmt.Printf("%s\nfelise version %s(c) 2023 sloum, all rights reserved\nLicensed under the terms of the Floodgap Free Software License\n(`bye` or `exit` to quit)\n\n", logo,VersionString())
|
||||
initialTerm, _ = ln.TerminalMode()
|
||||
line = ln.NewLiner()
|
||||
linerTerm, _ = ln.TerminalMode()
|
||||
defer line.Close()
|
||||
fmt.Printf("%s\nfelise version %s(c) 2023 sloum, all rights reserved\nLicensed under the terms of the Floodgap Free Software License\n(`bye` or `exit` to quit)\n\n", logo,VersionString())
|
||||
initialTerm, _ = ln.TerminalMode()
|
||||
line = ln.NewLiner()
|
||||
linerTerm, _ = ln.TerminalMode()
|
||||
defer line.Close()
|
||||
|
||||
line.SetCompleter(func(line string) (c []string) {
|
||||
index := strings.LastIndexAny(line, " ")
|
||||
for _, n := range completions {
|
||||
if index < 0 && strings.HasPrefix(string(n), line) {
|
||||
c = append(c, string(n))
|
||||
} else if len(line) > index+1 && strings.HasPrefix(string(n), line[index+1:]) {
|
||||
start := len(line) - index - 1
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
c = append(c, line+string(n)[start:])
|
||||
}
|
||||
}
|
||||
return
|
||||
})
|
||||
line.SetCompleter(func(line string) (c []string) {
|
||||
index := strings.LastIndexAny(line, " ")
|
||||
for _, n := range completions {
|
||||
if index < 0 && strings.HasPrefix(string(n), line) {
|
||||
c = append(c, string(n))
|
||||
} else if len(line) > index+1 && strings.HasPrefix(string(n), line[index+1:]) {
|
||||
start := len(line) - index - 1
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
c = append(c, line+string(n)[start:])
|
||||
}
|
||||
}
|
||||
return
|
||||
})
|
||||
|
||||
var text strings.Builder
|
||||
var cont bool
|
||||
baseEnv := NewEnv(nil)
|
||||
err := loadStdLib(baseEnv)
|
||||
if err != nil {
|
||||
processInterpretError(err, "std")
|
||||
}
|
||||
var text strings.Builder
|
||||
var cont bool
|
||||
baseEnv := NewEnv(nil)
|
||||
err := loadStdLib(baseEnv)
|
||||
if err != nil {
|
||||
processInterpretError(err, "std")
|
||||
}
|
||||
|
||||
for {
|
||||
if linerTerm != nil {
|
||||
linerTerm.ApplyMode()
|
||||
}
|
||||
in := prompt(line, cont)
|
||||
if initialTerm != nil {
|
||||
initialTerm.ApplyMode()
|
||||
}
|
||||
if s := strings.TrimSpace(in); s == "" {
|
||||
continue
|
||||
} else if s == "bye" || s == "exit" {
|
||||
break
|
||||
}
|
||||
if strings.HasSuffix(in, "\\") {
|
||||
cont = true
|
||||
text.WriteString(in[:len(in)-1])
|
||||
text.WriteRune('\n')
|
||||
} else {
|
||||
cont = false
|
||||
text.WriteString(in)
|
||||
}
|
||||
if !cont {
|
||||
processInterpretError(lexParseInterpret(text.String(), baseEnv, ""), "")
|
||||
text.Reset()
|
||||
}
|
||||
}
|
||||
for {
|
||||
if linerTerm != nil {
|
||||
linerTerm.ApplyMode()
|
||||
}
|
||||
in := prompt(line, cont)
|
||||
if initialTerm != nil {
|
||||
initialTerm.ApplyMode()
|
||||
}
|
||||
if s := strings.TrimSpace(in); s == "" {
|
||||
continue
|
||||
} else if s == "bye" || s == "exit" {
|
||||
break
|
||||
}
|
||||
if strings.HasSuffix(in, "\\") {
|
||||
cont = true
|
||||
text.WriteString(in[:len(in)-1])
|
||||
text.WriteRune('\n')
|
||||
} else {
|
||||
cont = false
|
||||
text.WriteString(in)
|
||||
}
|
||||
if !cont {
|
||||
processInterpretError(lexParseInterpret(text.String(), baseEnv, ""), "")
|
||||
text.Reset()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func lexParseInterpret(s string, en *env, file string) error {
|
||||
lexedTokens, err := lex(s, file)
|
||||
if err == nil {
|
||||
r := NewTokenReader(lexedTokens)
|
||||
var parsedTokens []token
|
||||
parsedTokens, err = parse(r)
|
||||
if err == nil {
|
||||
err = interpret(parsedTokens, en)
|
||||
}
|
||||
}
|
||||
lexedTokens, err := lex(s, file)
|
||||
if err == nil {
|
||||
r := NewTokenReader(lexedTokens)
|
||||
var parsedTokens []token
|
||||
parsedTokens, err = parse(r)
|
||||
if err == nil {
|
||||
err = interpret(parsedTokens, en)
|
||||
}
|
||||
}
|
||||
sort.Strings(completions)
|
||||
return err
|
||||
return err
|
||||
}
|
||||
|
||||
func processInterpretError(err error, file string) {
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "ERROR | %s\n", err.Error())
|
||||
if file == "" {
|
||||
globalStack.sp = 0
|
||||
} else {
|
||||
os.Exit(1)
|
||||
}
|
||||
} else if file == "" {
|
||||
fmt.Println("\n\033[0mOk.")
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "ERROR | %s\n", err.Error())
|
||||
if file == "" {
|
||||
globalStack.sp = 0
|
||||
} else {
|
||||
os.Exit(1)
|
||||
}
|
||||
} else if file == "" {
|
||||
fmt.Println("\n\033[0mOk.")
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
verFlag := flag.Bool("v", false, "Print version information and exit")
|
||||
flag.BoolVar(&debug, "debug", false, "Turns on debug mode")
|
||||
flag.Parse()
|
||||
flagArgs = flag.Args()
|
||||
verFlag := flag.Bool("v", false, "Print version information and exit")
|
||||
flag.BoolVar(&debug, "debug", false, "Turns on debug mode")
|
||||
flag.Parse()
|
||||
flagArgs = flag.Args()
|
||||
|
||||
if *verFlag {
|
||||
fmt.Print(VersionString())
|
||||
} else if len(flagArgs) > 0 {
|
||||
p := ExpandedAbsFilepath(flagArgs[0])
|
||||
s, err := readFile(p)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "felise could not read the given input file:\n `%s`\n", flagArgs[0])
|
||||
os.Exit(1)
|
||||
}
|
||||
en := NewEnv(nil)
|
||||
err = loadStdLib(en)
|
||||
if err != nil {
|
||||
processInterpretError(err, "std")
|
||||
}
|
||||
if len(flagArgs) > 1 {
|
||||
t := make([]token, len(flagArgs)-1)
|
||||
for i, s := range flagArgs[1:] {
|
||||
t[i] = token{STRING, s, -1, "built-in"}
|
||||
}
|
||||
en.Add("sys-args", token{LIST, list{t}, -1, "built-in"})
|
||||
} else {
|
||||
t := make([]token, 0)
|
||||
en.Add("sys-args", token{LIST, list{t}, -1, "built-in"})
|
||||
}
|
||||
processInterpretError(lexParseInterpret(s, en, flagArgs[0]), flagArgs[0])
|
||||
} else {
|
||||
repl()
|
||||
}
|
||||
if *verFlag {
|
||||
fmt.Print(VersionString())
|
||||
} else if len(flagArgs) > 0 {
|
||||
p := ExpandedAbsFilepath(flagArgs[0])
|
||||
s, err := readFile(p)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "felise could not read the given input file:\n `%s`\n", flagArgs[0])
|
||||
os.Exit(1)
|
||||
}
|
||||
en := NewEnv(nil)
|
||||
err = loadStdLib(en)
|
||||
if err != nil {
|
||||
processInterpretError(err, "std")
|
||||
}
|
||||
if len(flagArgs) > 1 {
|
||||
t := make([]token, len(flagArgs)-1)
|
||||
for i, s := range flagArgs[1:] {
|
||||
t[i] = token{STRING, s, -1, "built-in"}
|
||||
}
|
||||
en.Add("sys-args", token{LIST, list{t}, -1, "built-in"})
|
||||
} else {
|
||||
t := make([]token, 0)
|
||||
en.Add("sys-args", token{LIST, list{t}, -1, "built-in"})
|
||||
}
|
||||
processInterpretError(lexParseInterpret(s, en, flagArgs[0]), flagArgs[0])
|
||||
} else {
|
||||
repl()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue