Use proper package accessors instead. This was mostly already done. Removal of
package imports make it easier to tell when symbols do not belong to cmp.
It is worth noting that *active-protection* and *pending-actions* are generally
not used too (because *pending-actions* are never modified), but if we want to
add some useful semantics to with-compilation-unit one day then we'll need both.
The comment mentioned that aux variables (the sixth value) are returned the
same way as requireds, optionals and keywords however factually that was not
the case - the number of variables was not the first element of the list. This
commit updates the function and all its callers.
For functions already compiled and loaded, we simply check if the
definition is a closure. For functions defined in the same file, we
don't store their definition in the compiler environment but instead
use *global-funs*. The advantage is that this directly allows us to
determine whether a function is a closure or not and we don't have to
run the first compiler pass again each time we inline the function.
This commit also fixes some minor issues with the inline policy,
described in detail as follows:
1. The inline policy differed subtly between `proclaim` and `declaim`.
If a file like
(eval-when (:compile-toplevel)
(proclaim '(inline f)))
(defun f ...)
was compiled (but not loaded), subsequent compilations would inline
`f` but for
(declaim (inline f))
(defun f ...)
the function `f` would only get inlined if the file was compiled _and_
loaded. We now use the latter approach for both cases. Thus, calling
`compile-file` without `load` has no side-effects regarding whether
functions are inlined or not.
2. We did not distinguish between functions which were declared inline
at a global versus local level such that e.g. in
(locally
(declare (inline f))
(defun f ...))
the function f would get inlined outside the scope of the `locally`
form. This is changed now such that local inline declarations only
apply to the scope in which they are made.
3. Inline declarations were made by expanding into statements like
(eval-when (:compile-toplevel)
(c::declare-inline ...))
during the macroexpansion of `defun`. However this only works if the
`defun` appears at the toplevel and hence in code like
(declaim (inline f))
(let (...)
(defun f ...))
the function `f` could not get inlined later on in the same file. This
is fixed now by calling the code which should run during compilation
directly when macro expanding defun.
Split up the options into additional flags for the linker and
additional libraries.
Quoting from issue #636:
> Here's an example, attempting to link one object file named
example.o into an executable named example. Libcrypto here is
superfluous and should be removed by --as-needed:
```
LDFLAGS="-Wl,--as-needed"
LIBS="-lcrypto"
gcc ${LDFLAGS} ${LIBS} example.o -o example # doesn't link libcrypto!
gcc example.o ${LDFLAGS} ${LIBS} -o example # doesn't honor --as-needed!
gcc ${LDFLAGS} example.o ${LIBS} -o example # works great!
```
> In short, the placement of your -l<foo> flags differs from that of
all the other linker flags. Since ECL is only providing one big
variable ld-flags for all of the linker flags, there's no correct
way to pass in options like --as-needed and -l<foo> at the same
time.
Fixes#636.
The most notable change applies to the file fixup.lsp. Functions destined to
be generic are converted to their final version.
Previously this conversion was done in a few steps in order to avoid issues
with infinite recursion in dispatch. We achieve this by assigning to these new
generic function a simplified discriminating function:
(lamda (&rest args)
(unless (or (null *clos-booted*)
(specializers-match-p args specializers))
(apply #'no-applicable-method generic-function args))
(apply old-function args))
The old function is also seeded as a primary method for the generic
function. This works correctly because functions have only one method so we
may directly call it (it is also a fine optimization strategy we do not
incorporate generally yet), and because the discriminating function will be
recomputed when other methods are added etc.
This way we may use these generic functions without issues directly with newly
redefined versions and the file is now ordered as follows:
- fixup early methods
- redefine functions to their final version
- convert functions to generics
- define missing methods
- implement the dependant maintenance protocol
After this file is loaded it is possible to use generic functions as usual.
Previously c1make-var checked whether the symbol NAME is CONSTANTP, but
ECL expands symbol macros in CONSTANTP so this returned false positives.
A similar concern applied to the CMP-ENV-REGISTER-SYMBOL-MACRO-FUNCTION.
C1EXPR-INNER when encountered a symbol tried to yield C1CONSTANT-VALUE
for if it iwas CONSTANTP - this was correct except for that we didn't
pass the environment to the predicate and symbols weren't shadowed.
In this commit one function is added to the core - si:constp (with
similar purpose to si:specialp) and one function to the compiler -
constant-variable-p (similar to special-variable-p) and they are
appropriately used when necessary. A regression test is added.
Fixes#662.
On Unix, pathnames are converted into the default encoding specified
by ext:*default-external-format* and back. On Windows, the operating
system already gives us utf16 encoded pathnames, so we use those.
ecl_namestring with ECL_NAMESTRING_FORCE_BASE_STRING encodes with the
specified encoding. Decoding is handled individually in the filesystem
functions.
Includes a minor refactor of list_directory, changing the
PARSE_DIRECTORY_ENTRY macro into an inline function.
Closes#609, #549.
The type propagation is invoked with a function compiler-pass/propagate-types
before the compiler-pass2. Previously the type propagation was invoked in
ctop-write.
- separate passes
The separation is not fine-grained but is a good starting point for further
cleanup. This is a preliminary requirement for multiple backends.
- use uninternet symbol in the package definition
- remove "execute" permission from all files
- remove a few unused functions
- rearrange loaded files
- less verbose compiler
Don't print "End of pass 1." message. This doesn't provide any valuable
information to the programmer.
Minor improvements to define-compiler-macro* (bail out if we detect
:allow-other-keys arguments, define a named block such that
return-from works as expected).
Major refactor of sequence compiler-macros: use define-compiler-macro*
which handles correct evaluation order, define new macro to handle
common stuff for all sequences compiler-macros (e.g. inline policy
checking, check that test and test-not are not both given). The main
expansion logic in the compiler macros is unchanged although the code
had to be slightly rewritten to accomodate the new macros.
Remove the now superfluous seq-opt-parse-args function.
Example:
(let ((x '(quote ...))) ...)
We really have to quote the value in all cases, si::maybe-quote would
strip away one level of quotation leaving only the equivalent
of (let ((x (quote ...))) ...) which of course is incorrect.
The previous version had several problems: argument evaluation order
was not handled correctly and the compiler-macro produced an error for
valid code like
(let ((etype :element-type))
(make-array 10 etype 'character))
Introduce a new generally applicable macro define-compiler-macro*
which fixes these issues.
Also search lexical environment for variables instead of only the
list of variables being established by the current form (which is nil
anyway in the case of locally; only let or multiple-value-bind
statements create new variables).
The declaration is still ignored, but fixing that would require a much
larger refactor because currently variable types are associated to the
variable itself. Thus the type can only be set for the full scope in
which the variable is active and not locally in some subscope.
We are transforming these functions into (loop :on ...). This simply
stops when the objects which we are looping on is not a list, but we
need to signal a type-error because the mapping functions are
specified to take only lists.
We were doing no error checking that we got the right number of
arguments. Also remove the manual creation of forms with a backquote
for better readability.
If a variable which is set with multiple-value-setq is bound to a
symbol-macro, we need to handle the order of side-effects as in setf.
Previously, we were first evaluating the value generating form
of the multiple-value-setq before setting the places from the
symbol-macro. The correct order is to first evaluate the forms from
the symbol macro giving the places to set, then evaluate the value
generating form from the multiple-value-setq and then set the places
to the generated values.
The ansi standard specifies that declaring symbols bound with
symbol-macrolet to be special or binding symbols that are defined as
global variables must signal a program-error. Previously, we simply
ignored this issues.
Also fix an issue with cmp-env-search-variables which would wrongly
return variables when searching for symbol macros. This allows us to
remove another check in symbol-macro-declaration-p.
If we inline a function which contains keyword arguments whose default
value depends on the presence of other keyword arguments as for
example in
(funcall (lambda (&key (a nil a-p) (b a-p)) ...))
where `b` depends on the presence of `a`, we need to set the
key-flag `a-p` immediately after scanning for the keyword and not at
the end after we have finished scanning all keywords as we did previously.