Add 'paths' support alongside with namespace loading to the Runtime
This commit is contained in:
parent
17e35aa2e9
commit
aa1079c6b6
|
@ -37,9 +37,7 @@ func rep(rt *Runtime, line string) {
|
||||||
|
|
||||||
// Debug data, ugly right ? :))
|
// Debug data, ugly right ? :))
|
||||||
if rt.IsDebugMode() {
|
if rt.IsDebugMode() {
|
||||||
fmt.Println("\n### DEBUG ###")
|
fmt.Printf("[DEBUG] Parsed AST: %s\n", ast.String())
|
||||||
Print(rt, ast)
|
|
||||||
fmt.Print("#############\n\n")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result, e := Eval(rt, ast)
|
result, e := Eval(rt, ast)
|
||||||
|
@ -57,7 +55,13 @@ Replace the readline implementation with go-prompt.
|
||||||
// REPL executes a Read Eval Print Loop locally reading from stdin and
|
// REPL executes a Read Eval Print Loop locally reading from stdin and
|
||||||
// writing to stdout
|
// writing to stdout
|
||||||
func REPL(debug bool) {
|
func REPL(debug bool) {
|
||||||
rt := MakeRuntime(debug)
|
cwd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rt := MakeRuntime([]string{cwd}, debug)
|
||||||
|
|
||||||
rt.CreateNS("user", "REPL", true)
|
rt.CreateNS("user", "REPL", true)
|
||||||
|
|
||||||
rl, err := readline.NewEx(&readline.Config{
|
rl, err := readline.NewEx(&readline.Config{
|
||||||
|
|
|
@ -20,6 +20,10 @@ package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
/** TODO:
|
/** TODO:
|
||||||
|
@ -29,10 +33,15 @@ Create an IRuntime interface to avoid using INamespace directly
|
||||||
/** TODO:
|
/** TODO:
|
||||||
Handle concurrency on the runtime level
|
Handle concurrency on the runtime level
|
||||||
*/
|
*/
|
||||||
|
type loadedForms struct {
|
||||||
|
source string
|
||||||
|
forms *Block
|
||||||
|
}
|
||||||
|
|
||||||
type Runtime struct {
|
type Runtime struct {
|
||||||
namespaces map[string]Namespace
|
namespaces map[string]Namespace
|
||||||
currentNS string
|
currentNS string
|
||||||
|
paths []string
|
||||||
debugMode bool
|
debugMode bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,6 +63,21 @@ func (r *Runtime) CurrentNS() *Namespace {
|
||||||
return &ns
|
return &ns
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Runtime) setCurrentNS(nsName string) bool {
|
||||||
|
_, ok := r.namespaces[nsName]
|
||||||
|
|
||||||
|
if ok {
|
||||||
|
r.currentNS = nsName
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Runtime) GetNS(ns string) (*Namespace, bool) {
|
||||||
|
namespace, ok := r.namespaces[ns]
|
||||||
|
return &namespace, ok
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Runtime) CreateNS(name string, source string, setAsCurrent bool) {
|
func (r *Runtime) CreateNS(name string, source string, setAsCurrent bool) {
|
||||||
ns := MakeNS(name, source)
|
ns := MakeNS(name, source)
|
||||||
|
|
||||||
|
@ -69,10 +93,81 @@ func (r *Runtime) IsQQSimplificationEnabled() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeRuntime(debug bool) *Runtime {
|
func nsNameToPath(ns string) string {
|
||||||
|
replacer := strings.NewReplacer(
|
||||||
|
".", "/",
|
||||||
|
//"-", "_",
|
||||||
|
)
|
||||||
|
return replacer.Replace(ns)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Runtime) LoadNS(ns string) (*loadedForms, IError) {
|
||||||
|
nsFile := nsNameToPath(ns)
|
||||||
|
for _, loadPath := range r.paths {
|
||||||
|
// TODO: Hardcoding the suffix??? ewwww, fix it.
|
||||||
|
possibleFile := path.Join(loadPath, nsFile+".srn")
|
||||||
|
|
||||||
|
_, err := os.Stat(possibleFile)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := ioutil.ReadFile(possibleFile)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
readError := MakeError(
|
||||||
|
r,
|
||||||
|
fmt.Sprintf("error while reading the file at %s", possibleFile),
|
||||||
|
)
|
||||||
|
readError.WithError(err)
|
||||||
|
return nil, readError
|
||||||
|
}
|
||||||
|
|
||||||
|
body, e := ReadString(string(data))
|
||||||
|
if e != nil {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
|
||||||
|
return &loadedForms{possibleFile, body}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Add the load paths to the error message here
|
||||||
|
return nil, MakeError(r, fmt.Sprintf("Can't find the namespace '%s' in any of load paths.", ns))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Runtime) RequireNS(ns string) (*Namespace, IError) {
|
||||||
|
// TODO: use a hashing algorithm to avoid reloading an unchanged namespace
|
||||||
|
loadedForms, err := r.LoadNS(ns)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
body := loadedForms.forms
|
||||||
|
source := loadedForms.source
|
||||||
|
|
||||||
|
if body.Count() == 0 {
|
||||||
|
return nil, MakeError(
|
||||||
|
r,
|
||||||
|
fmt.Sprintf("The '%s' ns source code doesn't start with an 'ns' form.", ns),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
namespace := MakeNS(ns, source)
|
||||||
|
namespace.setForms(body)
|
||||||
|
|
||||||
|
return &namespace, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Runtime) InsertNS(nsName string, ns *Namespace) {
|
||||||
|
r.namespaces[nsName] = *ns
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeRuntime(paths []string, debug bool) *Runtime {
|
||||||
return &Runtime{
|
return &Runtime{
|
||||||
namespaces: map[string]Namespace{},
|
namespaces: map[string]Namespace{},
|
||||||
currentNS: "",
|
currentNS: "",
|
||||||
debugMode: debug,
|
debugMode: debug,
|
||||||
|
paths: paths,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue