## core-tools.api
#
# The common core of both public and private interface
# to makelib's tools mechanism.
#
#
# Compiled by:
#
src/app/makelib/makelib.sublibstipulate
package fil = file__premicrothread; # file__premicrothread is from
src/lib/std/src/posix/file--premicrothread.pkg package mvi = makelib_version_intlist; # makelib_version_intlist is from
src/app/makelib/stuff/makelib-version-intlist.pkgherein
# This api is referenced in no packages;
# it is included in:
#
#
src/app/makelib/tools/main/private-makelib-tools.api #
api Core_Tools {
Ilk = String;
#
# We don't make ilks abstract.
# It doesn't look like there
# would be much point to it.
File_Path;
#
# We keep source paths abstract.
# Tool writers should not mess
# with their internals.
#
# The function that makes a srcpath
# from a string is passed as part of
# the input specification (type "spec").
#
# Which function is originally be passed
# depends on which syntax was used for
# this member in its .lib file.
#
# Most tools will want to work on
# native pathname syntax (function "outdated" -- see below -- depends
# on native syntax!).
#
# In these cases the tool should first convert
# the name to a srcpath and then get the native
# string back by applying "native_spec".
Dir_Path;
Renamings = List { anchor: String, value: Dir_Path }; # MUSTDIE
native_spec: File_Path -> String; # Get the spec (i.e., relative to the directory context) of a path:
native_pre_spec: Dir_Path -> String; # Same for Dir_Path...
srcpath: Dir_Path -> File_Path; # Make a File_Path from a Dir_Path, checking that the "at least one arc" rule is satisfied...
augment: Dir_Path -> List( String ) -> Dir_Path; # Augment a Dir_Path with extra arcs. The new path has inherits the context (i.e., any anchoring) from the original one.
exception TOOL_ERROR { tool: String, msg: String };
Pathmaker = Void -> Dir_Path;
Fnspec = { name: String, # A filename specification.
make_path: Pathmaker
};
Tool_Option # Case-by-case parameters that can be passed to tools...
#
= STRING Fnspec
#
| SUBOPTS { name: String,
tool_options: Tool_Options
}
withtype
Tool_Options = List( Tool_Option );
Tooloptcvt
=
Null_Or( Tool_Options ) ->
Null_Or( Tool_Options );
Spec
=
{ name: String,
make_path: Pathmaker,
#
ilk: Null_Or( Ilk ),
tool_options: Null_Or( Tool_Options ),
#
derived: Bool
};
#
# A member specification consists of the actual string, an optional
# ilk name, (optional) tool options, a function to convert a
# string to its corresponding srcpath, and information about whether
# or not this source is an "original" source or a derived source
# (i.e., output of some tool).
Inlining
=
Null_Or( Null_Or( Int ) ); # see ....controls::inline...
Controller
=
{ save_controller_state: Void -> Void -> Void, # Generate a thunk containing current controller state, which when run will restore controller to that state.
set: Void -> Void
};
#
# A controller is a generic mechanism for manipulating state.
#
# The first stage of save_controller_state is meant to capture the part of
# the state in question so that the second stage can restore it.
#
# Function 'set', on the other hand, serves to establish the
# new state.
#
# All controllers associated with a Mythryl source
# are invoked for both parsing and compilation.
#
# Roughly speaking, given a controller c, each of these two phases
# is bracketed as follows:
#
# { restore = c.save_controller_state ();
# c.set ();
# parse_or_compile ()
# then
# restore ();
# }
Ml_Parameters
=
{ share: sharing_mode::Request,
pre_compile_code: Null_Or(String),
postcompile_code: Null_Or(String),
split: Inlining,
noguid: Bool,
is_local: Bool,
controllers: List( Controller )
};
Makelib_Parameters
=
{ version: Null_Or( mvi::Makelib_Version_Intlist )
, renamings: Renamings # MUSTDIE
};
Expansion
=
{ source_files: List( (File_Path, Ml_Parameters) ),
makelib_files: List( (File_Path, Makelib_Parameters) ),
sources: List( (File_Path, { ilk: Ilk, derived: Bool }) )
};
#
# The goal of applying tools to members is to obtain an "expansion",
# i.e., a list of source-files and a list of .lib-files.
# We also obtain a list of "sources". This is used to implement makelib::sources,
# i.e., to generate dependency information etc.
Partial_Expansion # A partial expansion is an expansion with a list of things yet to be expanded...
=
(Expansion, List( Spec ));
Rulefn = Void -> Partial_Expansion;
#
# A rule takes a spec and a rulecontext
# where the name contained in the spec
# -- if relative -- is considered relative
# to the directory of the corresponding
# description file.
#
# In general, when coding a rule one would
# write a rule function and pass it to
# the context, which will temporarily change
# the current working directory to the one that
# holds the description file ("the context").
#
# If this is not necessary for the rule to work
# correctly, then one can simply ignore the
# context (this saves system call overhead
# during dependency analysis).
#
# If the rule yields a genuine partial expansion
# (where the resulting spec list is not empty),
# then it must pass the proper "path maker"
# along with each new name.
#
# For most cases this will be the given
# "native path maker" because most rules
# work on native path names.
#
# Some rules, however, might want to use
# the same convention for derived specs
# that was used for the original spec.
Rulecontext
=
Rulefn -> Partial_Expansion;
Rule
=
{ spec: Spec,
native2pathmaker: String -> Pathmaker,
context: Rulecontext,
default_ilk_of: Fnspec -> Null_Or( Ilk ),
sysinfo: { get_makelib_preprocessor_symbol_value: String -> Null_Or( Int ), # If given preprocessor symbol is defined, returns its Int value, otherwise returns NULL.
platform: String # "intel32-linux" or such.
}
}
->
Partial_Expansion;
note_ilk: (Ilk, Rule) -> Void; # Install an ilk:
# Classifiers are used when the ilk
# is not given explicitly:
#
Filename_Classifier
#
= FILENAME_SUFFIX_CLASSIFIER String -> Null_Or( Ilk )
#
| GENERAL_FILENAME_CLASSIFIER { name: String, make_filename: Void -> String }
->
Null_Or( Ilk )
;
standard_filename_suffix_classifier # Make a classifier which looks for a specific file name suffix.
:
{ suffix: String, ilk: Ilk } -> Filename_Classifier;
Extension_Style # Two standard ways of dealing with filename extensions...
# # (Tool options can be calculated from the options that we have.)
= EXTEND List ((String, Null_Or( Ilk ), Tooloptcvt))
| REPLACE (List( String ), List ((String, Null_Or( Ilk ), Tooloptcvt)))
;
# Perform filename extension
#
extend_filename
:
Extension_Style
->
(String, Null_Or(Tool_Options))
->
List ((String, Null_Or( Ilk ), Null_Or( Tool_Options )) )
;
# Check for outdated files; the pathname
# strings must be in native syntax!
#
outdated: String -> (List( String ), String) -> Bool;
# Alternative way of checking for outdated-ness
# using a "witness" file. The idea is that if
# both targetFileName and timestampFileName
# exist, then targetFileName is considered outdated
# if timestampFileName is older than sourceFileName.
#
# Otherwise, if targetFileName exists but timestampFileName does not,
# then targetFileName is considered outdated if it is older than
# sourceFileName. If targetFileName does not exist, it is
# always considered outdated.
#
outdated'
:
String
->
{ source_file_name: String,
timestamp_file_name: String,
target_file_name: String
}
->
Bool;
open_text_output # Open output file; make all necessary directories for it.
:
String -> fil::Output_Stream;
make_all_directories_on_path # Make all directories leading up to a given file;
: # the file itself is to be left alone.
String -> Void;
note_filename_classifier # Install a classifier.
:
Filename_Classifier -> Void;
parse_options # Grab all named options.
:
{ tool: String,
keywords: List( String ),
tool_options: Tool_Options
}
->
{ matches: String -> Null_Or( Tool_Options ),
remaining_options: List( String )
};
};
end;
# (C) 2000 Lucent Technologies, Bell Laboratories
# Author: Matthias Blume (blume@kurims.kyoto-u.ac.jp)
## Subsequent changes by Jeff Prothero Copyright (c) 2010-2015,
## released per terms of SMLNJ-COPYRIGHT.