Skip to content

Commit b64a8fb

Browse files
committed
Mark unbound .fvalue value to detect it in FBOUNDP
As we're binding the function to the symbol with .bind(), we lose the identity check for `unboundFunction`. Instead, mark the function with a special symbol so we can detect the symbol is unbound.
1 parent 73b9c07 commit b64a8fb

File tree

4 files changed

+24
-7
lines changed

4 files changed

+24
-7
lines changed

src/compiler/compiler.lisp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1221,7 +1221,7 @@
12211221
(convert-to-bool `(!== (get ,x "value") undefined)))
12221222

12231223
(define-builtin fboundp (x)
1224-
(convert-to-bool `(!== (get ,x "fvalue") (internal |unboundFunction|))))
1224+
(convert-to-bool `(call-internal |fboundp| ,x)))
12251225

12261226
(define-builtin symbol-value (x)
12271227
`(call-internal |symbolValue| ,x))

src/prelude.js

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ internals.forcemv = function(x) {
5959
return typeof x == 'object' && x !== null && 'multiple-value' in x? x: internals.mv(x);
6060
};
6161

62-
6362
//
6463
// Workaround the problems with `new` for arbitrary number of
6564
// arguments. Some primitive constructors (like Date) differ if they
@@ -331,15 +330,21 @@ packages.KEYWORD = {
331330

332331
jscl.CL = packages.CL.exports;
333332

334-
internals.unboundFunction = function () {
335-
throw new Error("Function '" + this.name + "' undefined");
333+
334+
335+
const UNBOUND = Symbol('UnboundFunction')
336+
337+
internals.makeUnboundFunction = function (symbol) {
338+
const fn = ()=>{ throw new Error("Function '" + symbol.name + "' undefined");}
339+
fn[UNBOUND] = true;
340+
return fn;
336341
};
337342

338343
internals.Symbol = function(name, package_name){
339344
this.name = name;
340345
this.package = package_name;
341346
this.value = undefined;
342-
this.fvalue = internals.unboundFunction.bind(this);
347+
this.fvalue = internals.makeUnboundFunction(this)
343348
this.stack = [];
344349
};
345350

@@ -352,9 +357,17 @@ internals.symbolValue = function (symbol){
352357
}
353358
};
354359

360+
internals.fboundp = function (symbol) {
361+
if (symbol instanceof internals.Symbol){
362+
return !symbol.fvalue[UNBOUND]
363+
} else {
364+
throw new Error(`${symbol} is not a symbol`)
365+
}
366+
}
367+
355368
internals.symbolFunction = function (symbol){
356369
var fn = symbol.fvalue;
357-
if (fn === internals.unboundFunction)
370+
if (fn[UNBOUND])
358371
symbol.fvalue();
359372
return fn;
360373
};

tests/defstruct.lisp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@
113113
(test
114114
(mv-eql
115115
(values
116-
(mapcar 'fboundp (list #'sbt-02-a #'sbt-02-p #'copy-sbt-02))
116+
(mapcar 'fboundp (list 'sbt-02-a 'sbt-02-p 'copy-sbt-02))
117117
(sbt-02-con)
118118
(sbt-02-con :foo 99)
119119
(sbt-02-a (sbt-02-con :foo 1234)))

tests/variables.lisp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,8 @@
2222
(let ((*special-defparameter* 2))
2323
(test (= (f) 2))))
2424

25+
26+
(test (not (fboundp 'abc)))
27+
28+
2529
;;; EOF

0 commit comments

Comments
 (0)