From 82d94f911150e1c9df1d5a44aa52d85637227afa Mon Sep 17 00:00:00 2001 From: Matthias Andreas Benkard Date: Sat, 16 Aug 2008 18:44:46 +0200 Subject: %FSET, %FSETQ: Set global function bindings in a way that compiled code can understand. --- MLKLexicalEnvironment.m | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) (limited to 'MLKLexicalEnvironment.m') diff --git a/MLKLexicalEnvironment.m b/MLKLexicalEnvironment.m index fbeb9aa..ca6b4a9 100644 --- a/MLKLexicalEnvironment.m +++ b/MLKLexicalEnvironment.m @@ -24,8 +24,10 @@ #import #import +#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 -- cgit v1.2.3