fixing arity checks
This commit is contained in:
parent
05c37fe6d0
commit
398de4c1b0
|
@ -12,7 +12,8 @@
|
||||||
assemble-whole-prefix-reference
|
assemble-whole-prefix-reference
|
||||||
assemble-reg
|
assemble-reg
|
||||||
assemble-label
|
assemble-label
|
||||||
assemble-input)
|
assemble-input
|
||||||
|
assemble-listof-assembled-values)
|
||||||
|
|
||||||
|
|
||||||
(: assemble-oparg (OpArg -> String))
|
(: assemble-oparg (OpArg -> String))
|
||||||
|
@ -41,6 +42,8 @@
|
||||||
"MACHINE.proc"]
|
"MACHINE.proc"]
|
||||||
[(eq? target 'val)
|
[(eq? target 'val)
|
||||||
"MACHINE.val"]
|
"MACHINE.val"]
|
||||||
|
[(eq? target 'argcount)
|
||||||
|
"MACHINE.argcount"]
|
||||||
[(EnvLexicalReference? target)
|
[(EnvLexicalReference? target)
|
||||||
(assemble-lexical-reference target)]
|
(assemble-lexical-reference target)]
|
||||||
[(EnvPrefixReference? target)
|
[(EnvPrefixReference? target)
|
||||||
|
@ -71,6 +74,15 @@
|
||||||
[else
|
[else
|
||||||
(format "~s" val)])))
|
(format "~s" val)])))
|
||||||
|
|
||||||
|
(: assemble-listof-assembled-values ((Listof String) -> String))
|
||||||
|
(define (assemble-listof-assembled-values vals)
|
||||||
|
(let loop ([vals vals])
|
||||||
|
(cond
|
||||||
|
[(empty? vals)
|
||||||
|
"RUNTIME.NULL"]
|
||||||
|
[else
|
||||||
|
(format "[~a, ~a]" (first vals) (loop (rest vals)))])))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
36
assemble.rkt
36
assemble.rkt
|
@ -156,6 +156,8 @@ EOF
|
||||||
empty]
|
empty]
|
||||||
[(CheckClosureArity!? op)
|
[(CheckClosureArity!? op)
|
||||||
empty]
|
empty]
|
||||||
|
[(CheckPrimitiveArity!? op)
|
||||||
|
empty]
|
||||||
[(ExtendEnvironment/Prefix!? op)
|
[(ExtendEnvironment/Prefix!? op)
|
||||||
empty]
|
empty]
|
||||||
[(InstallClosureValues!? op)
|
[(InstallClosureValues!? op)
|
||||||
|
@ -337,7 +339,7 @@ EOF
|
||||||
[(MakeCompiledProcedure? op)
|
[(MakeCompiledProcedure? op)
|
||||||
(format "new RUNTIME.Closure(~a, ~a, [~a], ~a)"
|
(format "new RUNTIME.Closure(~a, ~a, [~a], ~a)"
|
||||||
(MakeCompiledProcedure-label op)
|
(MakeCompiledProcedure-label op)
|
||||||
(MakeCompiledProcedure-arity op)
|
(assemble-arity (MakeCompiledProcedure-arity op))
|
||||||
(string-join (map assemble-env-reference/closure-capture
|
(string-join (map assemble-env-reference/closure-capture
|
||||||
;; The closure values are in reverse order
|
;; The closure values are in reverse order
|
||||||
;; to make it easier to push, in bulk, into
|
;; to make it easier to push, in bulk, into
|
||||||
|
@ -350,7 +352,7 @@ EOF
|
||||||
[(MakeCompiledProcedureShell? op)
|
[(MakeCompiledProcedureShell? op)
|
||||||
(format "new RUNTIME.Closure(~a, ~a, undefined, ~a)"
|
(format "new RUNTIME.Closure(~a, ~a, undefined, ~a)"
|
||||||
(MakeCompiledProcedureShell-label op)
|
(MakeCompiledProcedureShell-label op)
|
||||||
(MakeCompiledProcedureShell-arity op)
|
(assemble-arity (MakeCompiledProcedureShell-arity op))
|
||||||
(assemble-display-name (MakeCompiledProcedureShell-display-name op)))]
|
(assemble-display-name (MakeCompiledProcedureShell-display-name op)))]
|
||||||
|
|
||||||
[(ApplyPrimitiveProcedure? op)
|
[(ApplyPrimitiveProcedure? op)
|
||||||
|
@ -382,6 +384,28 @@ EOF
|
||||||
(open-code-kernel-primitive-procedure op)]))
|
(open-code-kernel-primitive-procedure op)]))
|
||||||
|
|
||||||
|
|
||||||
|
(define-predicate natural? Natural)
|
||||||
|
|
||||||
|
(: assemble-arity (Arity -> String))
|
||||||
|
(define (assemble-arity an-arity)
|
||||||
|
(cond
|
||||||
|
[(natural? an-arity)
|
||||||
|
(format "~a" an-arity)]
|
||||||
|
[(ArityAtLeast? an-arity)
|
||||||
|
(format "(new RUNTIME.ArityAtLeast(~a))" (ArityAtLeast-value an-arity))]
|
||||||
|
[(listof-atomic-arity? an-arity)
|
||||||
|
(assemble-listof-assembled-values
|
||||||
|
(map (lambda: ([atomic-arity : (U Natural ArityAtLeast)])
|
||||||
|
(cond
|
||||||
|
[(natural? atomic-arity)
|
||||||
|
(format "~a" an-arity)]
|
||||||
|
[(ArityAtLeast? an-arity)
|
||||||
|
(format "(new RUNTIME.ArityAtLeast(~a))" (ArityAtLeast-value an-arity))]
|
||||||
|
;; Can't seem to make the type checker happy without this...
|
||||||
|
[else (error 'assemble-arity)]))
|
||||||
|
an-arity))]))
|
||||||
|
|
||||||
|
|
||||||
(: assemble-default-continuation-prompt-tag (-> String))
|
(: assemble-default-continuation-prompt-tag (-> String))
|
||||||
(define (assemble-default-continuation-prompt-tag)
|
(define (assemble-default-continuation-prompt-tag)
|
||||||
"RUNTIME.DEFAULT_CONTINUATION_PROMPT_TAG")
|
"RUNTIME.DEFAULT_CONTINUATION_PROMPT_TAG")
|
||||||
|
@ -402,7 +426,13 @@ EOF
|
||||||
(CheckToplevelBound!-pos op))]
|
(CheckToplevelBound!-pos op))]
|
||||||
|
|
||||||
[(CheckClosureArity!? op)
|
[(CheckClosureArity!? op)
|
||||||
(format "if (! (MACHINE.proc instanceof RUNTIME.Closure && MACHINE.proc.arity === MACHINE.val)) { if (! (MACHINE.proc instanceof RUNTIME.Closure)) { throw new Error(\"not a closure\"); } else { throw new Error(\"arity failure\"); } }")]
|
(format "if (! (MACHINE.proc instanceof RUNTIME.Closure && RUNTIME.isArityMatching(MACHINE.proc.arity, ~a))) { if (! (MACHINE.proc instanceof RUNTIME.Closure)) { throw new Error(\"not a closure\"); } else { throw new Error(\"arity failure:\" + MACHINE.proc.displayName); } }"
|
||||||
|
(assemble-oparg (CheckClosureArity!-arity op)))]
|
||||||
|
|
||||||
|
[(CheckPrimitiveArity!? op)
|
||||||
|
(format "if (! (typeof(MACHINE.proc) === 'function' && RUNTIME.isArityMatching(MACHINE.proc.arity, ~a))) { if (! (typeof(MACHINE.proc) === 'function')) { throw new Error(\"not a primitive procedure\"); } else { throw new Error(\"arity failure:\" + MACHINE.proc.displayName); } }"
|
||||||
|
(assemble-oparg (CheckPrimitiveArity!-arity op)))]
|
||||||
|
|
||||||
|
|
||||||
[(ExtendEnvironment/Prefix!? op)
|
[(ExtendEnvironment/Prefix!? op)
|
||||||
(let: ([names : (Listof (U Symbol False ModuleVariable)) (ExtendEnvironment/Prefix!-names op)])
|
(let: ([names : (Listof (U Symbol False ModuleVariable)) (ExtendEnvironment/Prefix!-names op)])
|
||||||
|
|
|
@ -365,13 +365,13 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(define-type Arity (U Natural ArityAtLeast (Listof (U Natural ArityAtLeast))))
|
||||||
(define-type Arity (U Natural
|
|
||||||
ArityAtLeast
|
|
||||||
(Listof (U Natural ArityAtLeast))))
|
|
||||||
(define-struct: ArityAtLeast ([value : Natural])
|
(define-struct: ArityAtLeast ([value : Natural])
|
||||||
#:transparent)
|
#:transparent)
|
||||||
|
|
||||||
|
(define-predicate listof-atomic-arity? (Listof (U Natural ArityAtLeast)))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(define-predicate OpArg? OpArg)
|
(define-predicate OpArg? OpArg)
|
92
runtime.js
92
runtime.js
|
@ -29,14 +29,16 @@
|
||||||
var isNumber = function(x) { return typeof(x) === 'number'; };
|
var isNumber = function(x) { return typeof(x) === 'number'; };
|
||||||
|
|
||||||
var isPair = function(x) { return (typeof(x) == 'object' &&
|
var isPair = function(x) { return (typeof(x) == 'object' &&
|
||||||
x.length === 2) }
|
x.length === 2) };
|
||||||
|
|
||||||
var isVector = function(x) { return (typeof(x) == 'object' &&
|
var isVector = function(x) { return (typeof(x) == 'object' &&
|
||||||
x.length !== undefined) }
|
x.length !== undefined) };
|
||||||
|
|
||||||
var Machine = function() {
|
var Machine = function() {
|
||||||
this.callsBeforeTrampoline = 100;
|
this.callsBeforeTrampoline = 100;
|
||||||
this.val = undefined;
|
this.val = undefined;
|
||||||
this.proc = undefined;
|
this.proc = undefined;
|
||||||
|
this.argcount = undefined;
|
||||||
this.env = [];
|
this.env = [];
|
||||||
this.control = []; // Arrayof (U CallFrame PromptFrame)
|
this.control = []; // Arrayof (U CallFrame PromptFrame)
|
||||||
this.running = false;
|
this.running = false;
|
||||||
|
@ -234,10 +236,33 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// An arity is either a primitive number, an ArityAtLeast instance,
|
||||||
|
// or a list of either primitive numbers or ArityAtLeast instances.
|
||||||
|
|
||||||
var ArityAtLeast = function(n) {
|
var ArityAtLeast = function(n) {
|
||||||
this.value = n;
|
this.value = n;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// isArityMatching: arity natural -> boolean
|
||||||
|
// Produces true if n satisfies the arity.
|
||||||
|
var isArityMatching = function(arity, n) {
|
||||||
|
if (typeof(arity) === 'number') {
|
||||||
|
return arity === n;
|
||||||
|
} else if (arity instanceof ArityAtLeast) {
|
||||||
|
return n >= arity.value;
|
||||||
|
} else {
|
||||||
|
while (arity !== NULL) {
|
||||||
|
if (typeof(arity[0]) === 'number') {
|
||||||
|
if (arity[0] === n) { return true; }
|
||||||
|
} else if (arity instanceof ArityAtLeast) {
|
||||||
|
if (n >= arity[0].value) { return true; }
|
||||||
|
}
|
||||||
|
arity = arity[1];
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -248,40 +273,39 @@
|
||||||
// the bootstrapping code.
|
// the bootstrapping code.
|
||||||
var Primitives = {};
|
var Primitives = {};
|
||||||
Primitives['display'] = function(MACHINE, arity) {
|
Primitives['display'] = function(MACHINE, arity) {
|
||||||
testArity('display', arity, 1, 2);
|
|
||||||
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
||||||
var outputPort = MACHINE.params.currentOutputPort;
|
var outputPort = MACHINE.params.currentOutputPort;
|
||||||
if (arity == 2) {
|
if (arity === 2) {
|
||||||
outputPort = MACHINE.env[MACHINE.env.length-2];
|
outputPort = MACHINE.env[MACHINE.env.length-2];
|
||||||
}
|
}
|
||||||
outputPort.write(MACHINE, firstArg);
|
outputPort.write(MACHINE, firstArg);
|
||||||
};
|
};
|
||||||
// FIXME: need to make a case dispatch here on arity.
|
Primitives['display'].arity = [1, [2, NULL]];
|
||||||
Primitives['display'].arity = 1; //new ArityAtLeast(1);
|
Primitives['display'].displayName = 'display';
|
||||||
|
|
||||||
|
|
||||||
Primitives['newline'] = function(MACHINE, arity) {
|
Primitives['newline'] = function(MACHINE, arity) {
|
||||||
testArity('newline', arity, 0, 1);
|
|
||||||
var outputPort = MACHINE.params.currentOutputPort;
|
var outputPort = MACHINE.params.currentOutputPort;
|
||||||
if (arity == 1) {
|
if (arity === 1) {
|
||||||
outputPort = MACHINE.env[MACHINE.env.length-1];
|
outputPort = MACHINE.env[MACHINE.env.length-1];
|
||||||
}
|
}
|
||||||
outputPort.write(MACHINE, "\n");
|
outputPort.write(MACHINE, "\n");
|
||||||
};
|
};
|
||||||
Primitives['newline'].arity = 1; //new ArityAtLeast(1);
|
Primitives['newline'].arity = [0, [1, NULL]];
|
||||||
|
Primitives['newline'].displayName = 'newline';
|
||||||
|
|
||||||
|
|
||||||
Primitives['displayln'] = function(MACHINE, arity){
|
Primitives['displayln'] = function(MACHINE, arity){
|
||||||
testArity('displayln', arity, 1, 2);
|
|
||||||
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
||||||
var outputPort = MACHINE.params.currentOutputPort;
|
var outputPort = MACHINE.params.currentOutputPort;
|
||||||
if (arity == 2) {
|
if (arity === 2) {
|
||||||
outputPort = MACHINE.env[MACHINE.env.length-2];
|
outputPort = MACHINE.env[MACHINE.env.length-2];
|
||||||
}
|
}
|
||||||
outputPort.write(MACHINE, firstArg);
|
outputPort.write(MACHINE, firstArg);
|
||||||
outputPort.write(MACHINE, "\n");
|
outputPort.write(MACHINE, "\n");
|
||||||
};
|
};
|
||||||
Primitives['displayln'].arity = 1; //new ArityAtLeast(1);
|
Primitives['displayln'].arity = [1, [2, NULL]];
|
||||||
|
Primitives['displayln'].displayName = 'displayln';
|
||||||
|
|
||||||
Primitives['pi'] = Math.PI;
|
Primitives['pi'] = Math.PI;
|
||||||
|
|
||||||
|
@ -304,6 +328,7 @@
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
Primitives['='].arity = new ArityAtLeast(2);
|
Primitives['='].arity = new ArityAtLeast(2);
|
||||||
|
Primitives['='].displayName = '=';
|
||||||
|
|
||||||
|
|
||||||
Primitives['<'] = function(MACHINE, arity) {
|
Primitives['<'] = function(MACHINE, arity) {
|
||||||
|
@ -323,6 +348,7 @@
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
Primitives['<'].arity = new ArityAtLeast(2);
|
Primitives['<'].arity = new ArityAtLeast(2);
|
||||||
|
Primitives['<'].displayName = '<';
|
||||||
|
|
||||||
Primitives['>'] = function(MACHINE, arity) {
|
Primitives['>'] = function(MACHINE, arity) {
|
||||||
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
||||||
|
@ -341,6 +367,7 @@
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
Primitives['>'].arity = new ArityAtLeast(2);
|
Primitives['>'].arity = new ArityAtLeast(2);
|
||||||
|
Primitives['>'].displayName = '>';
|
||||||
|
|
||||||
Primitives['<='] = function(MACHINE, arity) {
|
Primitives['<='] = function(MACHINE, arity) {
|
||||||
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
||||||
|
@ -359,6 +386,7 @@
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
Primitives['<='].arity = new ArityAtLeast(2);
|
Primitives['<='].arity = new ArityAtLeast(2);
|
||||||
|
Primitives['<='].displayName = '<=';
|
||||||
|
|
||||||
|
|
||||||
Primitives['>='] = function(MACHINE, arity) {
|
Primitives['>='] = function(MACHINE, arity) {
|
||||||
|
@ -378,6 +406,7 @@
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
Primitives['>='].arity = new ArityAtLeast(2);
|
Primitives['>='].arity = new ArityAtLeast(2);
|
||||||
|
Primitives['>='].displayName = '>=';
|
||||||
|
|
||||||
|
|
||||||
Primitives['+'] = function(MACHINE, arity) {
|
Primitives['+'] = function(MACHINE, arity) {
|
||||||
|
@ -395,6 +424,7 @@
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
Primitives['+'].arity = new ArityAtLeast(0);
|
Primitives['+'].arity = new ArityAtLeast(0);
|
||||||
|
Primitives['+'].displayName = '+';
|
||||||
|
|
||||||
|
|
||||||
Primitives['*'] = function(MACHINE, arity) {
|
Primitives['*'] = function(MACHINE, arity) {
|
||||||
|
@ -412,6 +442,7 @@
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
Primitives['*'].arity = new ArityAtLeast(0);
|
Primitives['*'].arity = new ArityAtLeast(0);
|
||||||
|
Primitives['*'].displayName = '*';
|
||||||
|
|
||||||
Primitives['-'] = function(MACHINE, arity) {
|
Primitives['-'] = function(MACHINE, arity) {
|
||||||
if (arity === 1) {
|
if (arity === 1) {
|
||||||
|
@ -434,6 +465,7 @@
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
Primitives['-'].arity = new ArityAtLeast(1);
|
Primitives['-'].arity = new ArityAtLeast(1);
|
||||||
|
Primitives['-'].displayName = '-';
|
||||||
|
|
||||||
Primitives['/'] = function(MACHINE, arity) {
|
Primitives['/'] = function(MACHINE, arity) {
|
||||||
testArgument('number',
|
testArgument('number',
|
||||||
|
@ -448,6 +480,8 @@
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
Primitives['/'].arity = new ArityAtLeast(1);
|
Primitives['/'].arity = new ArityAtLeast(1);
|
||||||
|
Primitives['/'].displayName = '/';
|
||||||
|
|
||||||
|
|
||||||
Primitives['cons'] = function(MACHINE, arity) {
|
Primitives['cons'] = function(MACHINE, arity) {
|
||||||
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
||||||
|
@ -455,6 +489,7 @@
|
||||||
return [firstArg, secondArg];
|
return [firstArg, secondArg];
|
||||||
};
|
};
|
||||||
Primitives['cons'].arity = 2;
|
Primitives['cons'].arity = 2;
|
||||||
|
Primitives['cons'].displayName = 'cons';
|
||||||
|
|
||||||
|
|
||||||
Primitives['list'] = function(MACHINE, arity) {
|
Primitives['list'] = function(MACHINE, arity) {
|
||||||
|
@ -466,6 +501,7 @@
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
Primitives['list'].arity = new ArityAtLeast(0);
|
Primitives['list'].arity = new ArityAtLeast(0);
|
||||||
|
Primitives['list'].displayName = 'list';
|
||||||
|
|
||||||
Primitives['car'] = function(MACHINE, arity) {
|
Primitives['car'] = function(MACHINE, arity) {
|
||||||
testArgument('pair',
|
testArgument('pair',
|
||||||
|
@ -477,6 +513,7 @@
|
||||||
return firstArg[0];
|
return firstArg[0];
|
||||||
};
|
};
|
||||||
Primitives['car'].arity = 1;
|
Primitives['car'].arity = 1;
|
||||||
|
Primitives['car'].displayName = 'car';
|
||||||
|
|
||||||
Primitives['cdr'] = function(MACHINE, arity) {
|
Primitives['cdr'] = function(MACHINE, arity) {
|
||||||
testArgument('pair',
|
testArgument('pair',
|
||||||
|
@ -488,12 +525,14 @@
|
||||||
return firstArg[1];
|
return firstArg[1];
|
||||||
};
|
};
|
||||||
Primitives['cdr'].arity = 1;
|
Primitives['cdr'].arity = 1;
|
||||||
|
Primitives['cdr'].displayName = 'cdr';
|
||||||
|
|
||||||
Primitives['pair?'] = function(MACHINE, arity) {
|
Primitives['pair?'] = function(MACHINE, arity) {
|
||||||
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
||||||
return isPair(firstArg);
|
return isPair(firstArg);
|
||||||
};
|
};
|
||||||
Primitives['pair?'].arity = 1;
|
Primitives['pair?'].arity = 1;
|
||||||
|
Primitives['pair?'].displayName = 'pair?';
|
||||||
|
|
||||||
Primitives['set-car!'] = function(MACHINE, arity) {
|
Primitives['set-car!'] = function(MACHINE, arity) {
|
||||||
testArgument('pair',
|
testArgument('pair',
|
||||||
|
@ -505,7 +544,8 @@
|
||||||
var secondArg = MACHINE.env[MACHINE.env.length-2];
|
var secondArg = MACHINE.env[MACHINE.env.length-2];
|
||||||
firstArg[0] = secondArg;
|
firstArg[0] = secondArg;
|
||||||
};
|
};
|
||||||
Primitives['set-car!'].arity = 1;
|
Primitives['set-car!'].arity = 2;
|
||||||
|
Primitives['set-car!'].displayName = 'set-car!';
|
||||||
|
|
||||||
Primitives['set-cdr!'] = function(MACHINE, arity) {
|
Primitives['set-cdr!'] = function(MACHINE, arity) {
|
||||||
testArgument('pair',
|
testArgument('pair',
|
||||||
|
@ -517,13 +557,15 @@
|
||||||
var secondArg = MACHINE.env[MACHINE.env.length-2];
|
var secondArg = MACHINE.env[MACHINE.env.length-2];
|
||||||
firstArg[1] = secondArg;
|
firstArg[1] = secondArg;
|
||||||
};
|
};
|
||||||
Primitives['set-cdr!'].arity = 1;
|
Primitives['set-cdr!'].arity = 2;
|
||||||
|
Primitives['set-cdr!'].displayName = 'set-cdr!';
|
||||||
|
|
||||||
Primitives['not'] = function(MACHINE, arity) {
|
Primitives['not'] = function(MACHINE, arity) {
|
||||||
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
||||||
return (!firstArg);
|
return (!firstArg);
|
||||||
};
|
};
|
||||||
Primitives['not'].arity = 1;
|
Primitives['not'].arity = 1;
|
||||||
|
Primitives['not'].displayName = 'not';
|
||||||
|
|
||||||
Primitives['null'] = NULL;
|
Primitives['null'] = NULL;
|
||||||
|
|
||||||
|
@ -532,6 +574,7 @@
|
||||||
return firstArg === NULL;
|
return firstArg === NULL;
|
||||||
};
|
};
|
||||||
Primitives['null?'].arity = 1;
|
Primitives['null?'].arity = 1;
|
||||||
|
Primitives['null?'].displayName = 'null?';
|
||||||
|
|
||||||
Primitives['add1'] = function(MACHINE, arity) {
|
Primitives['add1'] = function(MACHINE, arity) {
|
||||||
testArgument('number',
|
testArgument('number',
|
||||||
|
@ -543,6 +586,7 @@
|
||||||
return firstArg + 1;
|
return firstArg + 1;
|
||||||
};
|
};
|
||||||
Primitives['add1'].arity = 1;
|
Primitives['add1'].arity = 1;
|
||||||
|
Primitives['add1'].displayName = 'add1';
|
||||||
|
|
||||||
Primitives['sub1'] = function(MACHINE, arity) {
|
Primitives['sub1'] = function(MACHINE, arity) {
|
||||||
testArgument('number',
|
testArgument('number',
|
||||||
|
@ -554,12 +598,14 @@
|
||||||
return firstArg - 1;
|
return firstArg - 1;
|
||||||
};
|
};
|
||||||
Primitives['sub1'].arity = 1;
|
Primitives['sub1'].arity = 1;
|
||||||
|
Primitives['sub1'].displayName = 'sub1';
|
||||||
|
|
||||||
Primitives['zero?'] = function(MACHINE, arity) {
|
Primitives['zero?'] = function(MACHINE, arity) {
|
||||||
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
||||||
return firstArg === 0;
|
return firstArg === 0;
|
||||||
};
|
};
|
||||||
Primitives['zero?'].arity = 1;
|
Primitives['zero?'].arity = 1;
|
||||||
|
Primitives['zero?'].displayName = 'zero?';
|
||||||
|
|
||||||
Primitives['vector'] = function(MACHINE, arity) {
|
Primitives['vector'] = function(MACHINE, arity) {
|
||||||
var i;
|
var i;
|
||||||
|
@ -570,6 +616,7 @@
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
Primitives['vector'].arity = new ArityAtLeast(0);
|
Primitives['vector'].arity = new ArityAtLeast(0);
|
||||||
|
Primitives['vector'].displayName = 'vector';
|
||||||
|
|
||||||
Primitives['vector->list'] = function(MACHINE, arity) {
|
Primitives['vector->list'] = function(MACHINE, arity) {
|
||||||
testArgument('vector',
|
testArgument('vector',
|
||||||
|
@ -586,6 +633,7 @@
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
Primitives['vector->list'].arity = 1;
|
Primitives['vector->list'].arity = 1;
|
||||||
|
Primitives['vector->list'].displayName = 'vector->list';
|
||||||
|
|
||||||
Primitives['list->vector'] = function(MACHINE, arity) {
|
Primitives['list->vector'] = function(MACHINE, arity) {
|
||||||
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
||||||
|
@ -597,6 +645,7 @@
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
Primitives['list->vector'].arity = 1;
|
Primitives['list->vector'].arity = 1;
|
||||||
|
Primitives['list->vector'].displayName = 'list->vector';
|
||||||
|
|
||||||
Primitives['vector-ref'] = function(MACHINE, arity) {
|
Primitives['vector-ref'] = function(MACHINE, arity) {
|
||||||
testArgument('vector',
|
testArgument('vector',
|
||||||
|
@ -609,6 +658,7 @@
|
||||||
return firstArg[secondArg];
|
return firstArg[secondArg];
|
||||||
};
|
};
|
||||||
Primitives['vector-ref'].arity = 2;
|
Primitives['vector-ref'].arity = 2;
|
||||||
|
Primitives['vector-ref'].displayName = 'vector-ref';
|
||||||
|
|
||||||
Primitives['vector-set!'] = function(MACHINE, arity) {
|
Primitives['vector-set!'] = function(MACHINE, arity) {
|
||||||
testArgument('vector',
|
testArgument('vector',
|
||||||
|
@ -623,18 +673,21 @@
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
Primitives['vector-set!'].arity = 3;
|
Primitives['vector-set!'].arity = 3;
|
||||||
|
Primitives['vector-set!'].displayName = 'vector-set!';
|
||||||
|
|
||||||
Primitives['symbol?'] = function(MACHINE, arity) {
|
Primitives['symbol?'] = function(MACHINE, arity) {
|
||||||
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
||||||
return typeof(firstArg) === 'string';
|
return typeof(firstArg) === 'string';
|
||||||
};
|
};
|
||||||
Primitives['symbol?'].arity = 1;
|
Primitives['symbol?'].arity = 1;
|
||||||
|
Primitives['symbol?'].displayName = 'symbol?';
|
||||||
|
|
||||||
Primitives['symbol->string'] = function(MACHINE, arity) {
|
Primitives['symbol->string'] = function(MACHINE, arity) {
|
||||||
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
||||||
return firstArg;
|
return firstArg;
|
||||||
};
|
};
|
||||||
Primitives['symbol->string'].arity = 1;
|
Primitives['symbol->string'].arity = 1;
|
||||||
|
Primitives['symbol->string'].displayName = 'symbol->string';
|
||||||
|
|
||||||
Primitives['string-append'] = function(MACHINE, arity) {
|
Primitives['string-append'] = function(MACHINE, arity) {
|
||||||
var buffer = [];
|
var buffer = [];
|
||||||
|
@ -645,12 +698,14 @@
|
||||||
return buffer.join('');
|
return buffer.join('');
|
||||||
};
|
};
|
||||||
Primitives['string-append'].arity = new ArityAtLeast(0);
|
Primitives['string-append'].arity = new ArityAtLeast(0);
|
||||||
|
Primitives['string-append'].displayName = 'string-append';
|
||||||
|
|
||||||
Primitives['string-length'] = function(MACHINE, arity) {
|
Primitives['string-length'] = function(MACHINE, arity) {
|
||||||
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
||||||
return firstArg.length;
|
return firstArg.length;
|
||||||
};
|
};
|
||||||
Primitives['string-length'].arity = 1;
|
Primitives['string-length'].arity = 1;
|
||||||
|
Primitives['string-length'].displayName = 'string-length';
|
||||||
|
|
||||||
Primitives['box'] = function(MACHINE, arity) {
|
Primitives['box'] = function(MACHINE, arity) {
|
||||||
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
||||||
|
@ -658,12 +713,14 @@
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
Primitives['box'].arity = 1;
|
Primitives['box'].arity = 1;
|
||||||
|
Primitives['box'].displayName = 'box';
|
||||||
|
|
||||||
Primitives['unbox'] = function(MACHINE, arity) {
|
Primitives['unbox'] = function(MACHINE, arity) {
|
||||||
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
||||||
return firstArg[0];
|
return firstArg[0];
|
||||||
};
|
};
|
||||||
Primitives['unbox'].arity = 1;
|
Primitives['unbox'].arity = 1;
|
||||||
|
Primitives['unbox'].displayName = 'unbox';
|
||||||
|
|
||||||
Primitives['set-box!'] = function(MACHINE, arity) {
|
Primitives['set-box!'] = function(MACHINE, arity) {
|
||||||
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
||||||
|
@ -672,11 +729,13 @@
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
Primitives['set-box!'].arity = 2;
|
Primitives['set-box!'].arity = 2;
|
||||||
|
Primitives['set-box!'].displayName = 'set-box!';
|
||||||
|
|
||||||
Primitives['void'] = function(MACHINE, arity) {
|
Primitives['void'] = function(MACHINE, arity) {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
Primitives['void'].arity = new ArityAtLeast(0);
|
Primitives['void'].arity = new ArityAtLeast(0);
|
||||||
|
Primitives['void'].displayName = 'void';
|
||||||
|
|
||||||
Primitives['eq?'] = function(MACHINE, arity) {
|
Primitives['eq?'] = function(MACHINE, arity) {
|
||||||
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
||||||
|
@ -684,6 +743,7 @@
|
||||||
return firstArg === secondArg;
|
return firstArg === secondArg;
|
||||||
};
|
};
|
||||||
Primitives['eq?'].arity = 2;
|
Primitives['eq?'].arity = 2;
|
||||||
|
Primitives['eq?'].displayName = 'eq?';
|
||||||
|
|
||||||
Primitives['equal?'] = function(MACHINE, arity) {
|
Primitives['equal?'] = function(MACHINE, arity) {
|
||||||
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
var firstArg = MACHINE.env[MACHINE.env.length-1];
|
||||||
|
@ -708,6 +768,7 @@
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
Primitives['equal?'].arity = 2;
|
Primitives['equal?'].arity = 2;
|
||||||
|
Primitives['equal?'].displayName = 'equal?';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -793,6 +854,9 @@
|
||||||
exports['isOutputPort'] = isOutputPort;
|
exports['isOutputPort'] = isOutputPort;
|
||||||
exports['isOutputStringPort'] = isOutputStringPort;
|
exports['isOutputStringPort'] = isOutputStringPort;
|
||||||
|
|
||||||
|
exports['ArityAtLeast'] = ArityAtLeast;
|
||||||
|
exports['isArityMatching'] = isArityMatching;
|
||||||
|
|
||||||
exports['heir'] = heir;
|
exports['heir'] = heir;
|
||||||
exports['makeClassPredicate'] = makeClassPredicate;
|
exports['makeClassPredicate'] = makeClassPredicate;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#lang racket/base
|
#lang racket/base
|
||||||
(require "simulator-structs.rkt"
|
(require "simulator-structs.rkt"
|
||||||
|
"il-structs.rkt"
|
||||||
racket/math
|
racket/math
|
||||||
(for-syntax racket/base))
|
(for-syntax racket/base))
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
|
|
||||||
(define-struct: machine ([val : SlotValue]
|
(define-struct: machine ([val : SlotValue]
|
||||||
[proc : SlotValue]
|
[proc : SlotValue]
|
||||||
|
[argcount : SlotValue]
|
||||||
[env : (Listof SlotValue)]
|
[env : (Listof SlotValue)]
|
||||||
[control : (Listof frame)]
|
[control : (Listof frame)]
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
[else
|
[else
|
||||||
program-text])])
|
program-text])])
|
||||||
(let: ([m : machine (make-machine (make-undefined)
|
(let: ([m : machine (make-machine (make-undefined)
|
||||||
|
(make-undefined)
|
||||||
(make-undefined)
|
(make-undefined)
|
||||||
'()
|
'()
|
||||||
'()
|
'()
|
||||||
|
@ -126,7 +127,9 @@
|
||||||
(cond [(eq? reg 'val)
|
(cond [(eq? reg 'val)
|
||||||
(jump! m (ensure-symbol (machine-val m)))]
|
(jump! m (ensure-symbol (machine-val m)))]
|
||||||
[(eq? reg 'proc)
|
[(eq? reg 'proc)
|
||||||
(jump! m (ensure-symbol (machine-proc m)))])]))])))
|
(jump! m (ensure-symbol (machine-proc m)))]
|
||||||
|
[(eq? reg 'argcount)
|
||||||
|
(error 'goto "argcount misused as jump source")])]))])))
|
||||||
|
|
||||||
(: step-assign-immediate! (machine AssignImmediateStatement -> 'ok))
|
(: step-assign-immediate! (machine AssignImmediateStatement -> 'ok))
|
||||||
(define (step-assign-immediate! m stmt)
|
(define (step-assign-immediate! m stmt)
|
||||||
|
@ -194,7 +197,9 @@
|
||||||
(cond [(eq? reg 'val)
|
(cond [(eq? reg 'val)
|
||||||
(machine-val m)]
|
(machine-val m)]
|
||||||
[(eq? reg 'proc)
|
[(eq? reg 'proc)
|
||||||
(machine-proc m)]))
|
(machine-proc m)]
|
||||||
|
[(eq? reg 'argcount)
|
||||||
|
(machine-argcount m)]))
|
||||||
|
|
||||||
|
|
||||||
(: lookup-env-reference/closure-capture (machine EnvReference -> SlotValue))
|
(: lookup-env-reference/closure-capture (machine EnvReference -> SlotValue))
|
||||||
|
@ -339,6 +344,8 @@
|
||||||
proc-update!]
|
proc-update!]
|
||||||
[(eq? t 'val)
|
[(eq? t 'val)
|
||||||
val-update!]
|
val-update!]
|
||||||
|
[(eq? t 'argcount)
|
||||||
|
argcount-update!]
|
||||||
[(EnvLexicalReference? t)
|
[(EnvLexicalReference? t)
|
||||||
(lambda: ([m : machine] [v : SlotValue])
|
(lambda: ([m : machine] [v : SlotValue])
|
||||||
(if (EnvLexicalReference-unbox? t)
|
(if (EnvLexicalReference-unbox? t)
|
||||||
|
@ -562,7 +569,9 @@
|
||||||
[(eq? n 'proc)
|
[(eq? n 'proc)
|
||||||
(machine-proc m)]
|
(machine-proc m)]
|
||||||
[(eq? n 'val)
|
[(eq? n 'val)
|
||||||
(machine-val m)]))]
|
(machine-val m)]
|
||||||
|
[(eq? n 'argcount)
|
||||||
|
(machine-argcount m)]))]
|
||||||
|
|
||||||
[(EnvLexicalReference? an-oparg)
|
[(EnvLexicalReference? an-oparg)
|
||||||
(let*: ([v : SlotValue
|
(let*: ([v : SlotValue
|
||||||
|
@ -704,7 +713,7 @@
|
||||||
(: current-instruction (machine -> Statement))
|
(: current-instruction (machine -> Statement))
|
||||||
(define (current-instruction m)
|
(define (current-instruction m)
|
||||||
(match m
|
(match m
|
||||||
[(struct machine (val proc env control pc text
|
[(struct machine (val proc argcount env control pc text
|
||||||
stack-size jump-table))
|
stack-size jump-table))
|
||||||
(vector-ref text pc)]))
|
(vector-ref text pc)]))
|
||||||
|
|
||||||
|
@ -715,6 +724,10 @@
|
||||||
(set-machine-val! m v)
|
(set-machine-val! m v)
|
||||||
'ok)
|
'ok)
|
||||||
|
|
||||||
|
(: argcount-update! (machine SlotValue -> 'ok))
|
||||||
|
(define (argcount-update! m v)
|
||||||
|
(set-machine-argcount! m v)
|
||||||
|
'ok)
|
||||||
|
|
||||||
(: proc-update! (machine SlotValue -> 'ok))
|
(: proc-update! (machine SlotValue -> 'ok))
|
||||||
(define (proc-update! m v)
|
(define (proc-update! m v)
|
||||||
|
@ -725,7 +738,7 @@
|
||||||
(: env-push! (machine SlotValue -> 'ok))
|
(: env-push! (machine SlotValue -> 'ok))
|
||||||
(define (env-push! m v)
|
(define (env-push! m v)
|
||||||
(match m
|
(match m
|
||||||
[(struct machine (val proc env control pc text stack-size jump-table))
|
[(struct machine (val proc argcount env control pc text stack-size jump-table))
|
||||||
(set-machine-env! m (cons v env))
|
(set-machine-env! m (cons v env))
|
||||||
(set-machine-stack-size! m (add1 stack-size))
|
(set-machine-stack-size! m (add1 stack-size))
|
||||||
'ok]))
|
'ok]))
|
||||||
|
@ -733,7 +746,7 @@
|
||||||
(: env-push-many! (machine (Listof SlotValue) -> 'ok))
|
(: env-push-many! (machine (Listof SlotValue) -> 'ok))
|
||||||
(define (env-push-many! m vs)
|
(define (env-push-many! m vs)
|
||||||
(match m
|
(match m
|
||||||
[(struct machine (val proc env control pc text stack-size jump-table))
|
[(struct machine (val proc argcount env control pc text stack-size jump-table))
|
||||||
(set-machine-env! m (append vs env))
|
(set-machine-env! m (append vs env))
|
||||||
(set-machine-stack-size! m (+ stack-size (length vs)))
|
(set-machine-stack-size! m (+ stack-size (length vs)))
|
||||||
'ok]))
|
'ok]))
|
||||||
|
@ -742,13 +755,13 @@
|
||||||
(: env-ref (machine Natural -> SlotValue))
|
(: env-ref (machine Natural -> SlotValue))
|
||||||
(define (env-ref m i)
|
(define (env-ref m i)
|
||||||
(match m
|
(match m
|
||||||
[(struct machine (val proc env control pc text stack-size jump-table))
|
[(struct machine (val proc argcount env control pc text stack-size jump-table))
|
||||||
(list-ref env i)]))
|
(list-ref env i)]))
|
||||||
|
|
||||||
(: env-mutate! (machine Natural SlotValue -> 'ok))
|
(: env-mutate! (machine Natural SlotValue -> 'ok))
|
||||||
(define (env-mutate! m i v)
|
(define (env-mutate! m i v)
|
||||||
(match m
|
(match m
|
||||||
[(struct machine (val proc env control pc text stack-size jump-table))
|
[(struct machine (val proc argcount env control pc text stack-size jump-table))
|
||||||
(set-machine-env! m (list-replace env i v))
|
(set-machine-env! m (list-replace env i v))
|
||||||
'ok]))
|
'ok]))
|
||||||
|
|
||||||
|
@ -766,7 +779,7 @@
|
||||||
(: env-pop! (machine Natural Natural -> 'ok))
|
(: env-pop! (machine Natural Natural -> 'ok))
|
||||||
(define (env-pop! m n skip)
|
(define (env-pop! m n skip)
|
||||||
(match m
|
(match m
|
||||||
[(struct machine (val proc env control pc text stack-size jump-table))
|
[(struct machine (val proc argcount env control pc text stack-size jump-table))
|
||||||
(set-machine-env! m (append (take env skip)
|
(set-machine-env! m (append (take env skip)
|
||||||
(drop env (+ skip n))))
|
(drop env (+ skip n))))
|
||||||
(set-machine-stack-size! m (ensure-natural (- stack-size n)))
|
(set-machine-stack-size! m (ensure-natural (- stack-size n)))
|
||||||
|
@ -776,7 +789,7 @@
|
||||||
(: control-push! (machine frame -> 'ok))
|
(: control-push! (machine frame -> 'ok))
|
||||||
(define (control-push! m a-frame)
|
(define (control-push! m a-frame)
|
||||||
(match m
|
(match m
|
||||||
[(struct machine (val proc env control pc text stack-size jump-table))
|
[(struct machine (val proc argcount env control pc text stack-size jump-table))
|
||||||
(set-machine-control! m (cons a-frame control))
|
(set-machine-control! m (cons a-frame control))
|
||||||
'ok]))
|
'ok]))
|
||||||
|
|
||||||
|
@ -784,14 +797,14 @@
|
||||||
(: control-pop! (machine -> 'ok))
|
(: control-pop! (machine -> 'ok))
|
||||||
(define (control-pop! m)
|
(define (control-pop! m)
|
||||||
(match m
|
(match m
|
||||||
[(struct machine (val proc env control pc text stack-size jump-table))
|
[(struct machine (val proc argcount env control pc text stack-size jump-table))
|
||||||
(set-machine-control! m (rest control))
|
(set-machine-control! m (rest control))
|
||||||
'ok]))
|
'ok]))
|
||||||
|
|
||||||
(: control-top (machine -> frame))
|
(: control-top (machine -> frame))
|
||||||
(define (control-top m)
|
(define (control-top m)
|
||||||
(match m
|
(match m
|
||||||
[(struct machine (val proc env control pc text stack-size jump-table))
|
[(struct machine (val proc argcount env control pc text stack-size jump-table))
|
||||||
(first control)]))
|
(first control)]))
|
||||||
|
|
||||||
|
|
||||||
|
@ -807,7 +820,7 @@
|
||||||
;; Jumps directly to the instruction at the given label.
|
;; Jumps directly to the instruction at the given label.
|
||||||
(define (jump! m l)
|
(define (jump! m l)
|
||||||
(match m
|
(match m
|
||||||
[(struct machine (val proc env control pc text stack-size jump-table))
|
[(struct machine (val proc argcount env control pc text stack-size jump-table))
|
||||||
(set-machine-pc! m (hash-ref jump-table l))
|
(set-machine-pc! m (hash-ref jump-table l))
|
||||||
'ok]))
|
'ok]))
|
||||||
|
|
||||||
|
|
|
@ -250,7 +250,7 @@
|
||||||
(list 0 1)
|
(list 0 1)
|
||||||
'closureStart))
|
'closureStart))
|
||||||
(make-PopEnvironment 2 0)
|
(make-PopEnvironment 2 0)
|
||||||
(make-PerformStatement (make-CheckClosureArity! 5)))))
|
(make-PerformStatement (make-CheckClosureArity! (make-Const 5))))))
|
||||||
|
|
||||||
;; this should fail, since the check is for 1, but the closure expects 5.
|
;; this should fail, since the check is for 1, but the closure expects 5.
|
||||||
(let/ec return
|
(let/ec return
|
||||||
|
@ -272,7 +272,7 @@
|
||||||
(list 0 1)
|
(list 0 1)
|
||||||
'closureStart))
|
'closureStart))
|
||||||
(make-PopEnvironment 2 0)
|
(make-PopEnvironment 2 0)
|
||||||
(make-PerformStatement (make-CheckClosureArity! 1)))))
|
(make-PerformStatement (make-CheckClosureArity! (make-Const 1))))))
|
||||||
(error 'expected-failure))
|
(error 'expected-failure))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -323,10 +323,12 @@
|
||||||
|
|
||||||
;; install-closure-values
|
;; install-closure-values
|
||||||
(let ([m
|
(let ([m
|
||||||
(make-machine (make-undefined) (make-closure 'procedure-entry
|
(make-machine (make-undefined)
|
||||||
0
|
(make-closure 'procedure-entry
|
||||||
(list 1 2 3)
|
0
|
||||||
'procedure-entry)
|
(list 1 2 3)
|
||||||
|
'procedure-entry)
|
||||||
|
(make-undefined)
|
||||||
(list true false) ;; existing environment holds true, false
|
(list true false) ;; existing environment holds true, false
|
||||||
'()
|
'()
|
||||||
0
|
0
|
||||||
|
@ -343,6 +345,7 @@
|
||||||
(let ([m
|
(let ([m
|
||||||
(make-machine (make-undefined)
|
(make-machine (make-undefined)
|
||||||
(make-closure 'procedure-entry 0 (list 1 2 3) 'procedure-entry)
|
(make-closure 'procedure-entry 0 (list 1 2 3) 'procedure-entry)
|
||||||
|
(make-undefined)
|
||||||
(list true false) ;; existing environment holds true, false
|
(list true false) ;; existing environment holds true, false
|
||||||
'()
|
'()
|
||||||
0
|
0
|
||||||
|
|
Loading…
Reference in New Issue
Block a user