diff --git a/globals.go b/globals.go index adbd8aa..9368004 100644 --- a/globals.go +++ b/globals.go @@ -46,5 +46,4 @@ var ( // This is the main stack for the language globalStack stack = NewStack() globalRetStack stack = NewStack() - imports = make(map[string]bool) ) diff --git a/interpret.go b/interpret.go index 24eee04..09d4f4e 100644 --- a/interpret.go +++ b/interpret.go @@ -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)] diff --git a/keywords.go b/keywords.go index 64a05a4..510d553 100644 --- a/keywords.go +++ b/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) diff --git a/lib/io.fe b/lib/io.fe deleted file mode 100644 index b45fa2d..0000000 --- a/lib/io.fe +++ /dev/null @@ -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 -. - diff --git a/lib/std.fe b/lib/std.fe index cf0d874..30e5712 100644 --- a/lib/std.fe +++ b/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) diff --git a/main.go b/main.go index a322c71..4e5e77c 100644 --- a/main.go +++ b/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:] {