summaryrefslogtreecommitdiff
path: root/MLKLexicalEnvironment.m
diff options
context:
space:
mode:
Diffstat (limited to 'MLKLexicalEnvironment.m')
-rw-r--r--MLKLexicalEnvironment.m52
1 files changed, 52 insertions, 0 deletions
diff --git a/MLKLexicalEnvironment.m b/MLKLexicalEnvironment.m
index fbeb9aa..ca6b4a9 100644
--- a/MLKLexicalEnvironment.m
+++ b/MLKLexicalEnvironment.m
@@ -24,8 +24,10 @@
#import <Foundation/NSString.h>
#import <Foundation/NSThread.h>
+#import "MLKCompiledClosure.h"
#import "MLKCons.h"
#import "MLKEnvironment.h"
+#import "MLKLexicalContext.h"
#import "MLKLexicalEnvironment.h"
#import "MLKPackage.h"
#import "MLKParenReader.h"
@@ -141,11 +143,61 @@ static MLKLexicalEnvironment *global_environment;
-(void) setFunction:(id)value forSymbol:(MLKSymbol *)symbol
{
[_functions setValue:value forSymbol:symbol];
+
+ if ([_functions environmentForSymbol:symbol] == global_environment->_functions)
+ {
+ // If we're changing the global environment, we need to
+ // interoperate with compiled code. In this case, be sure to set
+ // the global function cell.
+ //
+ // Note that this reserves memory for the function cell that is
+ // never freed, which is why we do it for global function bindings
+ // only!
+ id (**cell)(void *, ...) = [[MLKLexicalContext globalContext]
+ functionCellForSymbol:symbol];
+ void **closure_data_cell = [[MLKLexicalContext globalContext]
+ closureDataPointerForSymbol:symbol];
+ if ([value isKindOfClass:[MLKCompiledClosure class]])
+ {
+ *cell = (id (*)(void *, ...))[value code];
+ *closure_data_cell = [value closureData];
+ }
+ else
+ {
+ *cell = MLKInterpretedFunctionTrampoline;
+ *closure_data_cell = value;
+ }
+ }
}
-(void) addFunction:(id)value forSymbol:(MLKSymbol *)symbol
{
[_functions addValue:value forSymbol:symbol];
+
+ if (self == global_environment)
+ {
+ // If we're changing the global environment, we need to
+ // interoperate with compiled code. In this case, be sure to set
+ // the global function cell.
+ //
+ // Note that this reserves memory for the function cell that is
+ // never freed, which is why we do it for global function bindings
+ // only!
+ id (**cell)(void *, ...) = [[MLKLexicalContext globalContext]
+ functionCellForSymbol:symbol];
+ void **closure_data_cell = [[MLKLexicalContext globalContext]
+ closureDataPointerForSymbol:symbol];
+ if ([value isKindOfClass:[MLKCompiledClosure class]])
+ {
+ *cell = (id (*)(void *, ...))[value code];
+ *closure_data_cell = [value closureData];
+ }
+ else
+ {
+ *cell = MLKInterpretedFunctionTrampoline;
+ *closure_data_cell = value;
+ }
+ }
}
-(BOOL) fboundp:(MLKSymbol *)symbol