Skip to content

Commit 67757e6

Browse files
committed
Implement load-system
1 parent bb353e5 commit 67757e6

5 files changed

Lines changed: 135 additions & 10 deletions

File tree

docs/notes.md

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,26 @@
55
---------------------
66

77
- expand-system
8-
- make sure require can load a system
9-
- add load-system (system-designator)
10-
- :quux or 'quux or "quux"
8+
- system (not ASDF but similar) https://asdf.common-lisp.dev/asdf.html
9+
- add :pathname to system for the default location of component files
10+
- components
11+
- allow filename of (:file "filename")
12+
- other keywords in (:file "quux" :pathname "src-dir" :description "has random stuff in it")
13+
- :description string
14+
- :pathname pathname-specifier
15+
- if (:file quux) is used then file should be the file name only and :pathname indicates the dir
16+
17+
- require and load can not easily be made to do the same as load-system dues to circulat dependency
18+
- load alway create some kind of interface but maybe best to leave them as just loading the def and not fetch and load
19+
- load-system (system)
20+
- don't bother with &rest keys &key force force-not verbose version &allow-other-keys
21+
22+
- :quux or 'quux or "quux" for system
23+
- set *load-pathname* and *load-truename* during load and eval
24+
- defer package back to before loading
1125
- system files can/should be .asd
1226
- one defsystem in file, read, compile, eval to get system
27+
- other code before defsystem will not break
1328
- tell system fetch and load
1429
- use load-system to read in file, eval, and then call fetch and load
1530
- same as require and load but must receive system

pkg/gi/load-system.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// Copyright (c) 2026, Peter Ohler, All rights reserved.
2+
3+
package gi
4+
5+
import (
6+
"fmt"
7+
"os"
8+
9+
"github.com/ohler55/slip"
10+
"github.com/ohler55/slip/pkg/flavors"
11+
)
12+
13+
func defLoadSystem() {
14+
slip.Define(
15+
func(args slip.List) slip.Object {
16+
f := LoadSystem{Function: slip.Function{Name: "load-system", Args: args}}
17+
f.Self = &f
18+
return &f
19+
},
20+
&slip.FuncDoc{
21+
Name: "load-system",
22+
Args: []*slip.DocArg{
23+
{
24+
Name: "system",
25+
Type: "symbol|keyword|string",
26+
Text: "System designator of the system to load.",
27+
},
28+
{Name: "&optional"},
29+
{
30+
Name: "pathname",
31+
Type: "string",
32+
Text: "Directory the system .asd file is located in.",
33+
},
34+
},
35+
Return: "system",
36+
Text: `__load-system__ load the _system_ by fetching the component files
37+
and loading them using the __:fetch__ and __:load__ methods of the system. Unlike ASDF,
38+
searching for the system is limited to the __*package-load-path*__ unless an oprional
39+
_pathname_ is provided. The search looks for _system_ with a '.asd' extension.`,
40+
Examples: []string{
41+
`(load-system :quux "testdata") => #<system 12345>`,
42+
},
43+
}, &Pkg)
44+
}
45+
46+
// LoadSystem represents the load-system function.
47+
type LoadSystem struct {
48+
slip.Function
49+
}
50+
51+
// Call the function with the arguments provided.
52+
func (f *LoadSystem) Call(s *slip.Scope, args slip.List, depth int) slip.Object {
53+
slip.CheckArgCount(s, depth, f, args, 1, 2)
54+
cys := slip.MustBeString(args[0], "system")
55+
path, _ := s.Get(slip.Symbol("*package-load-path*")).(slip.String)
56+
dir := string(path)
57+
if 1 < len(args) {
58+
dir = slip.MustBeString(args[1], "pathname")
59+
}
60+
filepath := fmt.Sprintf("%s/%s.asd", dir, cys)
61+
currentPkg := slip.CurrentPackage
62+
defer func() {
63+
s.Set(slip.Symbol("*load-pathname*"), nil)
64+
s.Set(slip.Symbol("*load-truename*"), nil)
65+
slip.CurrentPackage = currentPkg
66+
}()
67+
s.Set(slip.Symbol("*load-pathname*"), slip.String(filepath))
68+
s.Set(slip.Symbol("*load-truename*"), slip.String(filepath))
69+
buf, err := os.ReadFile(filepath)
70+
if err != nil {
71+
slip.FilePanic(s, depth, slip.String(filepath), "loading system %s at %s: %s", cys, filepath, err)
72+
}
73+
code := slip.Read(buf, s)
74+
code.Compile()
75+
obj := code.Eval(s, nil)
76+
77+
sys, ok := obj.(*flavors.Instance)
78+
if !ok || sys.Class() != system {
79+
slip.ErrorPanic(s, depth, "The last expression in %s was not a defsystem.", filepath)
80+
}
81+
sys.Set(slip.Symbol("pathname"), slip.String(dir))
82+
83+
_ = sys.Receive(s, ":fetch", nil, depth+1)
84+
_ = sys.Receive(s, ":load", nil, depth+1)
85+
86+
return sys
87+
}

pkg/gi/pkg.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ func init() {
288288
defFindProcess()
289289
defCommand()
290290
defMakeCommand()
291+
defLoadSystem()
291292

292293
Pkg.Initialize(nil, &Env{})
293294

pkg/gi/system.go

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ Each list element starts with an operation name such as :test and is followed by
3232
to invoke to implement that operation. When system :run is called with key values those keys
3333
are bound to the values and are available to the function being called.
3434
`
35+
36+
systemPathnameDoc = "Filepath to the component files."
3537
)
3638

3739
var system *flavors.Flavor
@@ -54,6 +56,7 @@ func defSystem() *flavors.Flavor {
5456
"components": nil,
5557
"in-order-to": nil,
5658
"cache": nil,
59+
"pathname": nil,
5760
},
5861
nil, // inherit
5962
slip.List{ // options
@@ -64,7 +67,7 @@ func defSystem() *flavors.Flavor {
6467
slip.String(`Instances of this Flavor define a system similar to ASDF in common LISP
6568
(https://asdf.common-lisp.dev) but with some differences. A __system__ instance
6669
captures the information associated with a code that implements the
67-
system. This includes providence variables such as author, version, and source
70+
system. This includes provenance variables such as author, version, and source
6871
location to name a few.
6972
7073
Some of the differences when compared to ASDF are:
@@ -75,13 +78,13 @@ Some of the differences when compared to ASDF are:
7578
- The :components variable only allows for files and not modules.
7679
- The :depends-on variable differs to support git and other system sources.
7780
- The :in-order-to variable differs although it serves the same purpose.
78-
- The __system__ is a Flavor that also supports a :fetch method.
81+
- The __system__ is a Flavor that also supports :fetch and :load methods.
7982
- A :cache variable is included.
8083
8184
8285
The usual use of a __system__ instance is to first send the instance a :fetch
83-
method to cache sources and then invoke one of the operations defined in the
84-
:in-order-to variable.
86+
method to cache sources, followed by :load, and then invoke one of the
87+
operations defined in the :in-order-to variable if desired.
8588
8689
`),
8790
},
@@ -92,6 +95,7 @@ method to cache sources and then invoke one of the operations defined in the
9295
system.DefMethod(":load", "", systemLoadCaller{})
9396
system.DefMethod(":run", "", systemRunCaller{})
9497

98+
system.Document("pathname", systemPathnameDoc)
9599
system.Document("components", systemComponentsDoc)
96100
system.Document("cache", systemCacheDoc)
97101
system.Document("depends-on", systemDependsOnDoc)
@@ -179,6 +183,10 @@ func (caller systemLoadCaller) Call(s *slip.Scope, args slip.List, depth int) sl
179183
}
180184
gc := self.Get("components")
181185
if gc != nil {
186+
dir := "."
187+
if pn, _ := self.Get("pathname").(slip.String); 0 < len(pn) {
188+
dir = string(pn)
189+
}
182190
var components slip.List
183191
components, ok := gc.(slip.List)
184192
if !ok {
@@ -189,11 +197,12 @@ func (caller systemLoadCaller) Call(s *slip.Scope, args slip.List, depth int) sl
189197
if path, ok = comp.(slip.String); !ok {
190198
slip.TypePanic(s, depth, "component", comp, "string")
191199
}
192-
matches, _ := filepath.Glob(string(path))
200+
compPath := filepath.Join(dir, string(path))
201+
matches, _ := filepath.Glob(compPath)
193202
if len(matches) == 0 {
194-
matches, _ = filepath.Glob(string(path) + ".lisp")
203+
matches, _ = filepath.Glob(compPath + ".lisp")
195204
if len(matches) == 0 {
196-
slip.ErrorPanic(s, depth, "%s not found.", path)
205+
slip.ErrorPanic(s, depth, "%s.lisp not found.", compPath)
197206
}
198207
}
199208
for _, m := range matches {

test/gi/testdata/sister/sister.asd

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
(defsystem "sister"
2+
:author "pete"
3+
:maintainer "pete@ohler.com"
4+
:license "MIT"
5+
:version "v0.1.0"
6+
:homepage "https://github.com/ohler55/slip"
7+
:bug-tracker "https://github.com/ohler55/slip/issues"
8+
:source-control "https://github.com/ohler55/slip"
9+
:description "Just a sample."
10+
:cache "testout"
11+
:components '("sister")
12+
:in-order-to '((:sample (+ (sys-test) six))
13+
(:just-eval 3)))

0 commit comments

Comments
 (0)