Skip to content

Commit

Permalink
Fixed macro plugin loading and duplicate initialization.
Browse files Browse the repository at this point in the history
  • Loading branch information
CuppoJava committed Jul 28, 2024
2 parents 9810814 + e0d518a commit af2723e
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 32 deletions.
74 changes: 51 additions & 23 deletions compiler/macro-master.stanza
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ defpackage stz/macro-master :
import stz/sexp-serializer
import stz/sexp-checker
import stz/params
import stz/verbose

;============================================================
;========================= API ==============================
Expand All @@ -33,18 +34,11 @@ public defmulti filename (p:MacroPlugin) -> String
; macro contains a superset of the expected packages.
public defn load-macro-plugin (filename:String,
expected-packages:Maybe<Tuple<Symbol>>) -> MacroPlugin :
;Report macro plugin.
vprintln("Load macro plugin %~." % [filename])

;Load the macro dynamic library.
val lib =
try :
dynamic-library-open(ensure-slash(filename))
catch (e:Exception) :
throw(ErrorLoadingMacroPlugin(filename, e))

;Test that it's a valid macro plugin
test-validity(lib)

;Call its main function for initialization.
call-main(lib)
val lib = load-macro-dylib(filename)

;Create the interface for communicating with it.
val interface = PluginInterface(SExpIO())
Expand All @@ -58,10 +52,9 @@ public defn load-macro-plugin (filename:String,

;Check that the plugin supports the expected packages.
if not empty?(expected-packages) :
if not subset?(value!(expected-packages), supported-packages) :
throw(UnexpectedPackagesInPlugin(filename,
supported-packages,
value!(expected-packages)))
val missing = difference(value!(expected-packages), supported-packages)
if not empty?(missing) :
throw(UnexpectedPackagesInPlugin(filename, missing))

;Create the plugin
new MacroPlugin :
Expand All @@ -73,10 +66,47 @@ public defn load-macro-plugin (filename:String,
defmethod filename (this) :
filename

;Helper: Return true if xs is a subset of ys.
defn subset? (xs:Seqable<Symbol>, ys:Seqable<Symbol>) -> True|False :
;Helper: Return all items in 'xs' that does not exist in 'ys'.
defn difference (xs:Seqable<Symbol>, ys:Seqable<Symbol>) -> Tuple<Symbol> :
val ys-set = to-hashset<Symbol>(ys)
for x in xs all? : ys-set[x]
to-tuple $ for x in xs filter : not ys-set[x]

;============================================================
;================== Already Loaded Set ======================
;============================================================

;Each entry, PATH => LIB, means that the resolved path PATH
;has already been loaded and we retrieved and initialized
;library LIB.
val LOADED-LIBRARIES = HashTable<String,DynamicLibrary>()

;Load and initialize the given dynamic library.
defn load-macro-dylib (filename:String) -> DynamicLibrary :
try :
;Resolve the full path first.
val path = resolve-path!(ensure-slash(filename))

;Test whether the library has already been loaded.
match(get?(LOADED-LIBRARIES, path)) :
;Case: If the library has already been loaded, then
;just return it directly.
(dylib:DynamicLibrary) :
dylib
;Case: The library hasn't been loaded, so load and
;initialize it.
(f:False) :
;Load the library.
val dylib = dynamic-library-open(path)
;Ensure it is a macro plugin by running a simple
;handshake function.
test-validity(dylib)
;Initialize the macro.
call-main(dylib)
;And store it into the table.
LOADED-LIBRARIES[path] = dylib
dylib
catch (e:Exception) :
throw(ErrorLoadingMacroPlugin(filename, e))

;============================================================
;===================== Ensure Slash =========================
Expand Down Expand Up @@ -148,13 +178,11 @@ defmethod print (o:OutputStream, e:InvalidMacroPlugin) :
;packages.
public defstruct UnexpectedPackagesInPlugin <: MacroPluginError :
filename:String
supported-packages:Tuple<Symbol>
expected-packages:Tuple<Symbol>
missing:Tuple<Symbol>

defmethod print (o:OutputStream, e:UnexpectedPackagesInPlugin) :
print(o, "Unexpected packages supported by macro plugin %~. The plugin \
supports packages %_, but it was expected to support %_." % [
filename(e), quotes(supported-packages(e)), quotes(expected-packages(e))])
print(o, "The macro plugin %~ is missing syntax packages. It is stated to contain the \
%_ syntax packages but does not." % [filename(e), quotes(missing(e))])

;Helper: Add quotes and commas around names.
defn quotes (ss:Seqable<Symbol>) -> ? :
Expand Down
8 changes: 5 additions & 3 deletions compiler/macroexpander.stanza
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ defpackage stz/macroexpander :
import stz/core-macros
import stz/proj-manager
import stz/proj-ir
import stz/verbose

;============================================================
;====================== API =================================
Expand Down Expand Up @@ -116,9 +117,10 @@ public defn StanzaMacroexpander (sys:MacroSystem,
;Helper: Find a macro plugin using the proj file.
defn find-using-proj () -> MacroPlugin|False :
match(proj-manager:ProjManager) :
val filename = find-syntax-packages(proj-manager, packages)
match(filename:String) :
plugin(load-macro-from-file(LoadedFromProj, filename, One(packages)))
val plugin-details = find-syntax-packages(proj-manager, packages)
if not empty?(plugin-details) :
val [filename, stated-packages] = value!(plugin-details)
plugin(load-macro-from-file(LoadedFromProj, filename, One(stated-packages)))

;Helper: Return true if the root expander
;supports the given packages.
Expand Down
2 changes: 1 addition & 1 deletion compiler/params.stanza
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public defn compiler-flags () :
to-tuple(COMPILE-FLAGS)

;========= Stanza Configuration ========
public val STANZA-VERSION = [0 18 87]
public val STANZA-VERSION = [0 18 88]
public var STANZA-INSTALL-DIR:String = ""
public var OUTPUT-PLATFORM:Symbol = `platform
public var STANZA-PKG-DIRS:List<String> = List()
Expand Down
13 changes: 8 additions & 5 deletions compiler/proj-manager.stanza
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,11 @@ public defmulti find-package (l:ProjManager, name:Symbol) -> PkgLocation|False
public defmulti conditional-imports (l:ProjManager, packages:Seqable<Symbol>) -> Tuple<Symbol>

;Given the set of syntax packages we need, find the name of the plugin
;that supports all of them. Returns false if none could be found.
public defmulti find-syntax-packages (l:ProjManager, names:Tuple<Symbol>) -> String|False
;that supports all of them. If a plugin is found, then we return
;[filename, stated-packages] where:
;- filename: The filename of the macro plugin that supports the requested packages.
;- stated-packages: The syntax packages that the macro plugin is stated to support.
public defmulti find-syntax-packages (l:ProjManager, names:Tuple<Symbol>) -> Maybe<[String,Tuple<Symbol>]>

;Returns the list of all syntax-package groups listed in the
;.proj files.
Expand Down Expand Up @@ -201,7 +204,7 @@ public defn ProjManager (proj:ProjFile, params:ProjParams, auxfile:AuxFile) :
PkgLocation(name, src-path, pkg-file, read-pkg?)

;Find a set of syntax packages
defn find-syntax-packages (names:Tuple<Symbol>) -> String|False :
defn find-syntax-packages (names:Tuple<Symbol>) -> Maybe<[String,Tuple<Symbol>]> :
;Returns true if names is a superset of xs.
defn superset-of-names? (xs:Seqable<Symbol>) -> True|False :
val xs-set = to-hashset<Symbol>(xs)
Expand All @@ -214,9 +217,9 @@ public defn ProjManager (proj:ProjFile, params:ProjParams, auxfile:AuxFile) :
;Note: We implicitly add `core and `tests to the supported packages.
;These are implicitly supported by all plugins even if not
;listed by the user.
value? $ for stmt in syntax-packages first :
for stmt in syntax-packages first :
val added-packages = cat(`(core tests), packages(stmt))
if superset-of-names?(added-packages) : One(filename(stmt))
if superset-of-names?(added-packages) : One([filename(stmt), packages(stmt)])
else : None()

;Retrieve conditional imports
Expand Down

0 comments on commit af2723e

Please sign in to comment.