Finishes import functionality, improves completion to react to new procs getting added (but not vars), further error message improvements
This commit is contained in:
parent
93a4ebb4b8
commit
ccfc3537fe
|
@ -46,5 +46,4 @@ var (
|
|||
// This is the main stack for the language
|
||||
globalStack stack = NewStack()
|
||||
globalRetStack stack = NewStack()
|
||||
imports = make(map[string]bool)
|
||||
)
|
||||
|
|
|
@ -33,6 +33,7 @@ ReplacedSymbol:
|
|||
}
|
||||
case PROC:
|
||||
en.Add(t.val.(proc).name, t)
|
||||
completions = append(completions, t.val.(proc).name)
|
||||
case IF:
|
||||
v, err := globalStack.Pop()
|
||||
if err != nil {
|
||||
|
@ -112,7 +113,7 @@ ReplacedSymbol:
|
|||
case SYMBOL:
|
||||
foundIn, err := en.Find(t.val.(string))
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("%s (Line %d of %s)", err.Error(), t.line, t.file)
|
||||
}
|
||||
x := foundIn.vars[t.val.(string)]
|
||||
|
||||
|
|
11
keywords.go
11
keywords.go
|
@ -1281,11 +1281,6 @@ func libImport(line int, fp string, en *env) error {
|
|||
if t.kind != STRING {
|
||||
return fmt.Errorf("`import` expects a STRING on TOS, not %s", kindToString(t.kind))
|
||||
}
|
||||
// Use 'imports' var (found in globals.go) to mark once imported
|
||||
// XXX scratch that. Add a map to the env struct and mark them there
|
||||
// so that they can get imported wherever in scope, but never doubly
|
||||
// so? A way to search parent scopes for the value will be important
|
||||
// as well
|
||||
if en.Imported(t.val.(string)) {
|
||||
return nil
|
||||
}
|
||||
|
@ -1308,12 +1303,6 @@ func libImport(line int, fp string, en *env) error {
|
|||
return err
|
||||
}
|
||||
en.imports[t.val.(string)] = true
|
||||
case "io":
|
||||
err = lexParseInterpret(ioImport, en, "io")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
en.imports[t.val.(string)] = true
|
||||
default:
|
||||
p := ExpandedAbsFilepath(t.val.(string))
|
||||
s, err := readFile(p)
|
||||
|
|
28
lib/io.fe
28
lib/io.fe
|
@ -1,28 +0,0 @@
|
|||
STRING var! stdout
|
||||
"/dev/fd/1" set! stdout
|
||||
|
||||
STRING var! stderr
|
||||
"/dev/fd/2" set! stderr
|
||||
|
||||
STRING var! stdin
|
||||
"/dev/fd/0" set! stdin
|
||||
|
||||
STRING var! devnull
|
||||
"/dev/null" set! devnull
|
||||
|
||||
proc print
|
||||
| Stack: ANY
|
||||
Read :
|
||||
Push :
|
||||
Notes: Prints the value on TOS |
|
||||
STRING cast stdout file-write
|
||||
.
|
||||
|
||||
proc println
|
||||
| Stack: ANY
|
||||
Read :
|
||||
Push :
|
||||
Notes: Prints the value on TOS + a newline |
|
||||
STRING cast "\n" append stdout file-write
|
||||
.
|
||||
|
34
lib/std.fe
34
lib/std.fe
|
@ -1,3 +1,37 @@
|
|||
# std contains misc useful procedures and variables
|
||||
# that make working in felise easier, but are coded
|
||||
# in felise itself, rather than as built-in procs
|
||||
# writen in go
|
||||
|
||||
STRING var! stdout
|
||||
"/dev/fd/1" set! stdout
|
||||
|
||||
STRING var! stderr
|
||||
"/dev/fd/2" set! stderr
|
||||
|
||||
STRING var! stdin
|
||||
"/dev/fd/0" set! stdin
|
||||
|
||||
STRING var! devnull
|
||||
"/dev/null" set! devnull
|
||||
|
||||
proc print
|
||||
| Stack: ANY
|
||||
Read :
|
||||
Push :
|
||||
Notes: Prints the value on TOS |
|
||||
STRING cast stdout file-write
|
||||
.
|
||||
|
||||
proc println
|
||||
| Stack: ANY
|
||||
Read :
|
||||
Push :
|
||||
Notes: Prints the value on TOS + a newline |
|
||||
STRING cast "\n" append stdout file-write
|
||||
.
|
||||
|
||||
|
||||
proc! ++!
|
||||
| Stack:
|
||||
Read : SYMBOL(INT)
|
||||
|
|
72
main.go
72
main.go
|
@ -1,4 +1,8 @@
|
|||
/*
|
||||
_
|
||||
|, _ |. __ _
|
||||
| (/,||_) (/,
|
||||
|
||||
Copyright (C) 2023 Brian Evans (aka sloum). All rights reserved.
|
||||
|
||||
This source code is available under the terms of the ffsl, or,
|
||||
|
@ -23,9 +27,8 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
version float64 = 0.1
|
||||
nameo string = "felise"
|
||||
logo string = ` _
|
||||
version float64 = 0.2
|
||||
logo string = ` _
|
||||
|, _ |. __ _
|
||||
| (/,||_) (/,`
|
||||
)
|
||||
|
@ -35,13 +38,13 @@ 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", "return",
|
||||
"print", "println", "dup", "drop", "over", "swap", "cast", "type", "while",
|
||||
"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", "exit", "stdin", "stdout", "stderr", "devnull", "net-get",
|
||||
"->", "<-", "=>", "->!", "=>!", "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",
|
||||
}
|
||||
|
||||
//go:embed lib/std.fe
|
||||
|
@ -50,40 +53,9 @@ var stdImport string
|
|||
//go:embed lib/math.fe
|
||||
var mathImport string
|
||||
|
||||
//go:embed lib/io.fe
|
||||
var ioImport string
|
||||
|
||||
//go:embed lib/stack.fe
|
||||
var stackImport string
|
||||
|
||||
|
||||
/*
|
||||
|
||||
_
|
||||
|, _ |. __ _
|
||||
| (/,||_) (/,
|
||||
|
||||
TODO / Ideas / Etc.
|
||||
|
||||
del [varname/procname]
|
||||
Will remove the symbol and value from the symbol table,
|
||||
not sure if this is useful but it feels like it adds
|
||||
completeness
|
||||
|
||||
---
|
||||
|
||||
Builtins on radar:
|
||||
|
||||
- `%`, `not`
|
||||
|
||||
Need some way to respond to args given at runtime... may need
|
||||
an array for that. Or maybe not? Maybe an `arg` word can be
|
||||
defined so that: `0 INT flag myarg` would let someone pass an
|
||||
arg: `felise myfile.fe --myarg=24`, with the arg defaulting to
|
||||
0... does something like that work?
|
||||
|
||||
*/
|
||||
|
||||
func prompt(l *ln.State, cont bool) string {
|
||||
p := "> "
|
||||
|
||||
|
@ -102,6 +74,15 @@ func VersionString() string {
|
|||
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
|
||||
}
|
||||
|
||||
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()
|
||||
|
@ -128,6 +109,10 @@ func repl() {
|
|||
var text strings.Builder
|
||||
var cont bool
|
||||
baseEnv := NewEnv(nil)
|
||||
err := loadStdLib(baseEnv)
|
||||
if err != nil {
|
||||
processInterpretError(err, "std")
|
||||
}
|
||||
|
||||
for {
|
||||
if linerTerm != nil {
|
||||
|
@ -169,8 +154,6 @@ func lexParseInterpret(s string, en *env, file string) error {
|
|||
}
|
||||
return err
|
||||
}
|
||||
// TODO just separated lex and process err
|
||||
// Make sure all is working
|
||||
|
||||
func processInterpretError(err error, file string) {
|
||||
if err != nil {
|
||||
|
@ -185,7 +168,6 @@ func processInterpretError(err error, file string) {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO add file input
|
||||
func main() {
|
||||
verFlag := flag.Bool("v", false, "Print version information and exit")
|
||||
flag.BoolVar(&debug, "debug", false, "Turns on debug mode")
|
||||
|
@ -202,6 +184,10 @@ func main() {
|
|||
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:] {
|
||||
|
|
Loading…
Reference in New Issue