atomo-0.2: prelude/eco.atomo
Eco =
Object clone do:
{ -- all packages OK for loading
-- name -> [package]
packages = []
-- versions loaded by @use:
-- name -> package
loaded = []
}
Eco Package = Object clone
Eco Package new :=
Eco Package clone do:
{ version = 0 . 1
dependencies = []
include = []
executables = []
contexts = []
environment = Lobby
}
(e: Eco) initialize :=
e initialize: (Eco Package load-from: "package.eco")
(e: Eco) initialize: pkg :=
{ pkg dependencies each: { c |
e packages (find: c from) match: {
@none -> raise: @(package-unavailable: c from needed: c to)
-- filter out versions not satisfying our dependency
@(ok: d) ->
{ safe = d to (filter: { p | p version join: c to })
safe match: {
[] ->
raise: @(no-versions-of: d satisfy: c to for: pkg name)
-- initialize the first safe version of the package
(p . _) ->
{ -- remove unsafe versions from the ecosystem
d to = safe
e initialize: p
} call
}
} call
}
}
@ok
} call
(e: Eco) load :=
{ eco = Directory home </> ".eco" </> "lib"
when: Directory (exists?: eco) do: {
e packages =
Directory (contents: eco) map:
{ c |
versions = Directory (contents: (eco </> c))
pkgs = versions map:
{ v |
Eco Package load-from:
(eco </> c </> v </> "package.eco")
}
c -> pkgs (sort-by: { a b | a version < b version })
}
}
@ok
} call
Eco path-to: (c: Eco Package) :=
Eco path-to: c name version: c version
Eco path-to: (name: String) :=
Directory home </> ".eco" </> "lib" </> name
Eco path-to: pkg version: (v: Version) :=
(Eco path-to: pkg) </> (v as: String)
Eco executable: (name: String) :=
Directory home </> ".eco" </> "bin" </> name
Eco which-main: (path: String) :=
if: File (exists?: (path </> "main.hs"))
then: { "main.hs" }
else: { "main.atomo" }
Eco install: (path: String) :=
{ pkg = Eco Package load-from: (path </> "package.eco")
target = Eco path-to: pkg
contents = (Eco which-main: path) . ("package.eco" . pkg include)
Directory create-tree-if-missing: target
contents each:
{ c |
if: Directory (exists?: (path </> c))
then: { Directory copy: (path </> c) to: (target </> c) }
else: { File copy: (path </> c) to: (target </> c) }
}
pkg executables each:
{ e |
exe =
[ "#!/usr/bin/env atomo"
"load: " .. (path </> e to) show
] unlines
with-output-to: (Eco executable: e from) do: { exe print }
File set-executable: (Eco executable: e from) to: True
}
@ok
} call
Eco uninstall: (name: String) version: (version: Version) :=
{ path = Eco path-to: name version: version
pkg = Eco Package load-from: (path </> "package.eco")
Directory remove-recursive: path
pkg executables each:
{ e |
File remove: (Eco executable: e from)
}
@ok
} call
Eco uninstall: (name: String) :=
{ Directory (contents: (Eco path-to: name)) each:
{ v |
Eco uninstall: name version: (v as: Version)
}
@ok
} call
Eco Package load-from: (file: String) :=
Eco Package new do: { load: file }
(p: Eco Package) name: (n: String) :=
p name = n
(p: Eco Package) description: (d: String) :=
p description = d
(p: Eco Package) version: (v: Version) :=
p version = v
(p: Eco Package) author: (a: String) :=
p author = a
(p: Eco Package) include: (l: List) :=
p include = l
(p: Eco Package) depends-on: (ds: List) :=
p dependencies = ds map:
{ d |
if: (d is-a?: Association)
then: { d }
else: { d -> { True } }
}
(p: Eco Package) executables: (es: List) :=
p executables = es
Eco load: name version: check in: env :=
Eco packages (lookup: name) match: {
@none -> raise: @(package-unavailable: name)
@(ok: []) -> raise: @(no-package-versions: name)
@(ok: pkgs) ->
{ pkg =
pkgs (filter: { p | p version join: check }) match: {
[] -> raise: @(no-versions-of: name satisfy: check)
(p . _) -> p
}
path = Eco path-to: pkg
pkg contexts = pkg contexts << env super
env load: (path </> (Eco which-main: path))
pkg environment = env
when: name (in?: Eco loaded (map: @from)) not do:
{ Eco loaded = Eco loaded << (name -> pkg) }
env
} call
}
context use: (name: String) :=
context use: name version: { True }
context use: (name: String) version: (v: Version) :=
context use: name version: { == v }
context use: (name: String) version: (check: Block) :=
Eco loaded (lookup: name) match: {
@none -> (Eco load: name version: check in: context clone)
@(ok: p) ->
condition: {
p version (join: check) not ->
raise: @(incompatible-version-loaded: name needed: check)
(context in?: p contexts) -> p environment
otherwise ->
(Eco load: name version: check in: context clone)
}
}