## anchor-dictionary.api -- Operations over abstract names for source files.
# Compiled by:
#
src/app/makelib/paths/srcpath.sublib# Overview comments at bottom of file.
### "The lyf so short, the craft so long to lerne."
###
### --Geoffrey Chaucer
api Anchor_Dictionary {
# We define an exception to raise if
# we encounter an "impossible" byte
# sequence while unpickling, presumably
# as a result of diskfile corruption:
#
exception FORMAT;
File;
Path_Root; # Root of a file path -- essentially, "/...", "./..." or "$ROOT/..."
Anchor_Dictionary;
Anchor = String;
Dir_Path;
Renaming = { anchor: Anchor, value: Dir_Path }; # MUSTDIE
Renamings = List( Renaming ); # MUSTDIE
Key = File;
compare: (File, File) -> Order; # Compare paths for ordering
sync: Void -> Void; # Re-establish stability of ordering.
clear: Void -> Void; # Forget all known path names.
revalidate_cwd: Void -> Void; # Re-validate current working directory.
add_cwd_watcher: (String -> Void) -> Void; # Register a "client" module that wishes
# to be notified when the CWD changes.
# Currently never called.
# Make sure all such clients get notified
# about the CWD during next validation:
#
schedule_notification: Void -> Void;
# A default dictionary containing
# just the ROOT definition:
#
dictionary: Anchor_Dictionary;
# Destructive updates to anchor settings (for configuration)
#
set_anchor: (Anchor_Dictionary, Anchor, Null_Or(String)) -> Void; # Native host OS syntax!
get_anchor: (Anchor_Dictionary, Anchor) -> Null_Or(String);
print_anchors: (Anchor_Dictionary, String) -> Void;
# my keyvals_list: Map(X) -> List( key::Key * X )
src/lib/src/map.api# my listAnchorsi: Anchor_Dictionary -> List( Anchor * String) src/lib/src/ord-map.apk
# Make abstract paths:
# This is intended to support file_path args
# in the local host OS notation -- even if it is Windows:
#
from_native:
#
{ plaint_sink: String -> Void } # Where to send error messages.
->
{ path_root: Path_Root,
file_path: String
}
->
Dir_Path;
# This is intended to support file_path args
# in our standard unix-like notation:
#
from_standard':
#
{ plaint_sink: String -> Void, # Where to send error messages.
anchor_dictionary: Anchor_Dictionary
}
->
{ path_root: Path_Root, # Typically anchor_dictionary::cwd ().
file_path: String # E.g. "$ROOT/src/lib/core/init/init.cmi"
} # or "$ROOT/src/lib/std/standard.lib"
-> # or "$ROOT/src/lib/core/mythryl-compiler-compiler/mythryl-compiler-compiler-for-this-platform.lib".
Dir_Path;
# A simplified version of the above
# sufficient for most purposes:
#
from_standard:
Anchor_Dictionary
->
String /* filename */ # E.g. "$ROOT/src/lib/core/init/init.cmi"
-> # or "$ROOT/src/lib/std/standard.lib"
File; # or "$ROOT/src/lib/core/mythryl-compiler-compiler/mythryl-compiler-compiler-for-this-platform.lib".
extend: Dir_Path -> List(String) -> Dir_Path;
#
# Augment a basename (naming a directory) with a list of arcs.
file: Dir_Path -> File;
#
# Check that there is at least one arc (the actual filename!) after the path's path_root.
file_to_basename: File -> Dir_Path;
#
# To be able to pickle a file, turn it into a basename first...
# Directory paths (path_roots)
#
current_working_directory: Void -> Path_Root;
#
dir: File -> Path_Root;
# Get info out of abstract paths:
#
os_string: File -> String;
os_string' : File -> String; # Use relative path if shorter
abbreviate : String -> String; # Abbreviate any ROOT prefix
# Get path relative to the file's path_root;
# this will produce an absolute path if
# the original file_path was not relative --
# i.e., if it was anchored or absolute:
#
os_string_relative: File -> String;
# Same for basename:
#
os_string_basename_relative: Dir_Path -> String;
# Get name of path root:
#
os_string_dir: Path_Root -> String;
# Get name of basename:
#
os_string_basename: Dir_Path -> String;
# Get a human-readable (well, sort of) description:
#
describe: File -> String;
# Get a time stamp:
#
timestamp: File -> timestamp::Timestamp; # timestamp is from
src/app/makelib/paths/timestamp.pkg # Portable encodings that avoid whitespace:
#
encode: File -> String;
decode: Anchor_Dictionary -> String -> File;
encoding_is_absolute: String -> Bool;
#
# Check whether encoding (result
# of "encode") is absolute --
# i.e., not anchored and not relative:
pickle: { warn: (Bool, String) -> Void }
->
{ file: Dir_Path,
relative_to: File
}
->
List( List(String) );
unpickle: Anchor_Dictionary
->
{ pickled: List( List(String) ),
relative_to: File
}
->
Dir_Path;
};
# Overview:
#
# Per unix tradition, .lib files may refer to files using
# "absolute" file paths such as /aa/bb/cc/... or
# "relative" file paths such as aa/bb/cc/...
# where "aa" "bb" "cc" are called path "arcs".
#
# In addition, makelib supports
# "anchored" file paths such as $ROOT/aa/bb/cc/...
# where "$ROOT" is an "anchor variable".
# This allows us to move an entire directory of
# sourcefiles from one spot to another in the filesystem
# simply by updating one anchor variable setting.
#
# Furthermore, makelib file syntax allows anchor variables
# to have both a fixed default value, and also to be
# temporarily rebound to another value within a given
# syntactic scope: We refer to these as the "free"
# and "bound" values of the anchor variable respectively,
# by analogy with lambda calculus nomenclature.
#
# We give the arcs "." and ".." the special meanings
# of respectively "current" and "parent" directory.
#
# We also forbid whitespace in paths, to allow simple
# parsing of .lib files.
#
# Some hosts may allow use of "." ".." as normal
# arc names, and some host arc names may in fact include
# whitespace. We handle these cases by encoding the
# arc names using octal escape sequences like \x2d
# for each problematic character.
#
# Since the user may move around source files from
# time to time and update anchor variables accordingly,
# we attempt to evaluate anchor variables, and expressions
# involving them, as late as possible in the compilation
# process, by using thunks and lazy-style datastructure
# techniques as appropriate.
# This datastructure "laziness" is potentially
# problematic in the case of paths specified relative to
# the current working directory ("CWD"), since the CWD
# may change from time to time, and our "laziness" could
# thus result in a path being evaluated relative to an
# unexpected -- and wrong -- CWD value.
# To avoid this problem, we track the CWD and
# implement a system of notifications for when the
# CWD changes, so as to give the effect of evaluating
# path expressions as late as possible, but still
# relative to the expected CWD value.
#
# Another twist: The above unix-like path specification
# is portably supported on all platforms -- we call it
# "standard" notation -- but sometimes we need access to
# idiosyncratic functionalities of a particular host's
# path syntax, in particular to the ability to specify
# disk volumes on MS-DOS/MS-Windows, so we also support
# use of the "native" path notation of the host os.
# --> In .lib file surface syntax we use a leading "#" on <--
# --> native path expressions to distinguish them from <--
# --> standard path expressions. <--
#
# Yet another: We provide facilities to "pickle" and
# "unpickle" our file reference datastructures, which
# is to say, to serialize them as bytestrings suitable
# for storage in diskfiles and then deserialize such
# bytestrings back into live datastructures. This
# lets us propagate state between executions of makelib.
#
# We implement all this as follows:
#
# o Our "anchors" are simply strings, which
# we look up in string-keyed maps.
#
# o Paths aa/bb/cc/... are represented as lists of strings
# ["aa", "bb", "cc", ...]
# except that mostly we're interested in being able
# to add and remove arcs from the logical -end- of
# the path, so we usually use -reversed- path lists
# [ ..., "cc", "bb", "aa" ]
#
# o Anchor values are recorded in an "anchor_dictionary"
# which includes both a
# a "free" map recording the current free (default) values of anchors, and a
# a "bound" map recording current bound values of anchors.
#
# o We define type Path_Root to represent the root of a path.
#
#
#
# 2010-09-08 CrT: Matthias Blume uses this facility heavily in SML/NJ,
# which I find makes the code harder to read -- this
# is the opposite of declarative programming style,
# one has mentally execute the code to guess what
# directory a given anchor points to at a given point
# in the computation.
#
# Consequently, in the Mythryl codebase I have reduced
# the set of anchors used to the single ROOT anchor,
# which points to the root of the Mythryl source code
# tree and never changes during a compile.
#
# I'm inclined to think this entire facility can and
# should be considerably simplified to accord more
# with standard posix programming practive. It appears
# to do nothing that couldn't be done better with
# standard unix environment strings.
## Author: Matthias Blume
## Copyright (c) 2000 by Lucent Technologies, Bell Laboratories
## Subsequent changes by Jeff Prothero Copyright (c) 2010-2015,
## released per terms of SMLNJ-COPYRIGHT.