func use(ec *EvalCtx, modname string, pfilename *string) { if _, ok := ec.Evaler.Modules[modname]; ok { // Module already loaded. return } // Load the source. var filename, source string if pfilename != nil { filename = *pfilename var err error source, err = readFileUTF8(filename) maybeThrow(err) } else { // No filename; defaulting to $datadir/$modname.elv. dataDir, err := store.DataDir() maybeThrow(err) filename = dataDir + "/" + modname + ".elv" if _, err := os.Stat(filename); os.IsNotExist(err) { // File does not exist. Try loading from the table of builtin // modules. var ok bool if source, ok = builtinModules[modname]; ok { // Source is loaded. Do nothing more. filename = "<builtin module>" } else { throw(fmt.Errorf("cannot load %s: %s does not exist", modname, filename)) } } else { // File exists. Load it. source, err = readFileUTF8(filename) maybeThrow(err) } } // TODO(xiaq): Should handle failures when evaluting the module newEc := &EvalCtx{ ec.Evaler, filename, source, "module " + modname, Namespace{}, Namespace{}, ec.ports, nil, 0, len(source), } n, err := parse.Parse(source) maybeThrow(err) op, err := newEc.Compile(n) // TODO the err originates in another source, should add appropriate information. maybeThrow(err) op.Exec(newEc) ec.Evaler.Modules[modname] = newEc.local }
func use(ec *EvalCtx, modname string, pfilename *string) { if _, ok := ec.Evaler.Modules[modname]; ok { // Module already loaded. return } // Load the source. var filename, source string if pfilename != nil { filename = *pfilename var err error source, err = readFileUTF8(filename) maybeThrow(err) } else { // No filename; defaulting to $datadir/$modname.elv. dataDir, err := store.DataDir() maybeThrow(err) filename = dataDir + "/" + strings.Replace(modname, ":", "/", -1) + ".elv" if _, err := os.Stat(filename); os.IsNotExist(err) { // File does not exist. Try loading from the table of builtin // modules. var ok bool if source, ok = builtinModules[modname]; ok { // Source is loaded. Do nothing more. filename = "<builtin module>" } else { throw(fmt.Errorf("cannot load %s: %s does not exist", modname, filename)) } } else { // File exists. Load it. source, err = readFileUTF8(filename) maybeThrow(err) } } n, err := parse.Parse(filename, source) maybeThrow(err) // Make an empty namespace. local := Namespace{} // TODO(xiaq): Should handle failures when evaluting the module newEc := &EvalCtx{ ec.Evaler, "module " + modname, filename, source, local, Namespace{}, ec.ports, nil, true, 0, len(source), ec.addTraceback(), false, } op, err := newEc.Compile(n, filename, source) // TODO the err originates in another source, should add appropriate information. maybeThrow(err) // Load the namespace before executing. This avoids mutual and self use's to // result in an infinite recursion. ec.Evaler.Modules[modname] = local err = newEc.PEval(op) if err != nil { // Unload the namespace. delete(ec.Modules, modname) throw(err) } }