/* -*- mode: objc; coding: utf-8 -*- */ /* Toilet Lisp, a Common Lisp subset for the Étoilé runtime. * Copyright (C) 2008 Matthias Andreas Benkard. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #import "MLKCons.h" #import "MLKForm.h" #import "MLKInterpreter.h" #import "util.h" #import "special-symbols.h" #import #import #import #include #define MAKE_FORM(OBJECT) \ [MLKForm formWithObject:OBJECT \ inContext:_context \ forCompiler:_compiler] @implementation MLKForm +(void) initialize { ensure_symbols (); } -(id) initWithObject:(id)object inContext:(MLKLexicalContext *)context forCompiler:(id)compiler { self = [super init]; LASSIGN (_form, object); LASSIGN (_context, context); LASSIGN (_compiler, compiler); return [self complete]; } -(id) complete { return self; } +(Class) dispatchClassForObject:(id)object { if (MLKInstanceP (object) && [object isKindOfClass:[MLKCons class]]) return [MLKCompoundForm class]; else return [MLKAtomicForm class]; } +(id) formWithObject:(id)object inContext:(MLKLexicalContext *)context forCompiler:(id)compiler { Class cls = [self dispatchClassForObject:object]; if (cls != self) return [cls formWithObject:object inContext:context forCompiler:compiler]; else return LAUTORELEASE ([[self alloc] initWithObject:object inContext:context forCompiler:compiler]); } -(NSArray *) subforms { return [NSArray array]; } @end @implementation MLKAtomicForm +(Class) dispatchClassForObject:(id)object { if (MLKInstanceP (object) && [object isKindOfClass:[MLKSymbol class]]) return [MLKSymbolForm class]; else return [MLKSelfEvaluatingForm class]; } @end @implementation MLKSelfEvaluatingForm +(Class) dispatchClassForObject:(id)object { return self; } @end @implementation MLKSymbolForm // FIXME +(Class) dispatchClassForObject:(id)object { return self; } @end @implementation MLKCompoundForm -(id) complete { self = [super complete]; _head = [_form car]; _tail = [_form cdr]; return self; } +(Class) dispatchClassForObject:(id)object { id car = [object car]; if (car == CATCH) return [MLKCatchForm class]; else if (car == EVAL) return [MLKFunctionCallForm class]; else if (car == EVAL_WHEN) return [MLKEvalWhenForm class]; else if (car == _FOREIGN_LAMBDA) return [MLKForeignLambdaForm class]; else if (car == FUNCTION) return [MLKFunctionForm class]; else if (car == IF) return [MLKIfForm class]; else if (car == IN_PACKAGE) return [MLKInPackageForm class]; else if (car == _LAMBDA) return [MLKSimpleLambdaForm class]; else if (car == _MACROLET) return [MLKSimpleMacroletForm class]; else if (car == _FLET) return [MLKSimpleFletForm class]; else if (car == LET) return [MLKLetForm class]; else if (car == _LOOP) return [MLKSimpleLoopForm class]; else if (car == MULTIPLE_VALUE_CALL) return [MLKMultipleValueCallForm class]; else if (car == PROGN) return [MLKProgNForm class]; else if (car == PROGV) return [MLKProgVForm class]; else if (car == QUOTE) return [MLKQuoteForm class]; else if (car == SETQ) return [MLKSetQForm class]; else if (car == _FSETQ) return [MLKFSetQForm class]; else if (car == THROW) return [MLKThrowForm class]; else if (car == UNWIND_PROTECT) return [MLKUnwindProtectForm class]; else return [MLKSimpleCompoundForm class]; } @end @implementation MLKSimpleCompoundForm -(id) initWithObject:(id)object inContext:(MLKLexicalContext *)context forCompiler:(id)compiler { self = [super initWithObject:object inContext:context forCompiler:compiler]; if ([self class] != [MLKSimpleCompoundForm class]) { return self; } else if ([_head isKindOfClass:[MLKCons class]]) { LRELEASE (self); return LRETAIN ([MLKForm formWithObject:[MLKCons cons:FUNCALL with:object] inContext:context forCompiler:compiler]); } else if ([context symbolNamesMacro:_head]) { LRELEASE (self); return LRETAIN ([MLKMacroCallForm formWithObject:object inContext:context forCompiler:compiler]); } else { LRELEASE (self); return LRETAIN ([MLKFunctionCallForm formWithObject:object inContext:context forCompiler:compiler]); } } +(Class) dispatchClassForObject:(id)object { return self; } @end @implementation MLKMacroCallForm -(id) initWithObject:(id)object inContext:(MLKLexicalContext *)context forCompiler:(id)compiler { self = [super initWithObject:object inContext:context forCompiler:compiler]; id macrofun = [context macroForSymbol:_head]; //NSLog (@"Expanding: %@", MLKPrintToString (_form)); id expansion = denullify ([[macrofun applyToArray: [NSArray arrayWithObjects: _form, context, nil]] objectAtIndex:0]); //NSLog (@"=> %@", MLKPrintToString (expansion)); return LRETAIN ([MLKForm formWithObject:expansion inContext:context forCompiler:compiler]); } @end @implementation MLKBodyForm -(void) splitDeclarationsAndBody:(id)object { LASSIGN (_body, object); } -(void) processBody:(id)object inContext:(MLKLexicalContext *)context { id rest; NSMutableArray *bodyForms = [NSMutableArray array]; [self splitDeclarationsAndBody:object]; rest = _body; while (rest) { [bodyForms addObject:[MLKForm formWithObject:[rest car] inContext:context forCompiler:_compiler]]; rest = [rest cdr]; } LASSIGN (_bodyContext, context); LASSIGN (_bodyForms, bodyForms); } -(void) processBody:(id)object { [self processBody:object inContext:_context]; } -(NSArray *) subforms { return _bodyForms; } @end @implementation MLKDeclaringForm -(void) splitDeclarationsAndBody:(id)object { MLKSplitDeclarationsDocAndForms(&_declarations, NULL, &_body, object, NO); } -(id) declarationsWithForms:(id)object { [self splitDeclarationsAndBody:object]; return _declarations; } -(NSArray *) subforms { return [[super subforms] arrayByAddingObjectsFromArray:_declarationForms]; } @end @implementation MLKDocstringForm -(void) splitDeclarationsAndBody:(id)object { MLKSplitDeclarationsDocAndForms(&_declarations, &_documentation, &_body, object, YES); } @end @implementation MLKFunctionCallForm -(id) complete { self = [super complete]; id rest; NSMutableArray *argumentForms = [NSMutableArray array]; rest = [_form cdr]; while (rest) { [argumentForms addObject:[MLKForm formWithObject:[rest car] inContext:_context forCompiler:_compiler]]; rest = [rest cdr]; } LASSIGN (_argumentForms, argumentForms); return self; } -(NSArray *) subforms { return [[super subforms] arrayByAddingObjectsFromArray:_argumentForms]; } @end @implementation MLKCatchForm -(id) complete { self = [super complete]; LASSIGN (_tagForm, [_tail car]); LASSIGN (_bodyForms, [[_tail cdr] array]); return self; } -(NSArray *) subforms { return [[[super subforms] arrayByAddingObject:_tagForm] arrayByAddingObjectsFromArray:_bodyForms]; } @end @implementation MLKEvalWhenForm -(id) complete { id rest; self = [super complete]; rest = [_tail car]; while (rest) { _compileToplevel |= ([rest car] == COMPILE_TOPLEVEL); _loadToplevel |= ([rest car] == LOAD_TOPLEVEL); _execute |= ([rest car] == EXECUTE); rest = [rest cdr]; } [self processBody:[_tail cdr]]; return self; } @end @implementation MLKForeignLambdaForm -(id) complete { id argtypes; int i; self = [super complete]; LASSIGN (_foreignName, [_tail car]); LASSIGN (_foreignLibraryDesignator, [[_tail cdr] car]); _returnType = MLKForeignTypeWithTypeDesignator ([[[[_tail cdr] cdr] cdr] car]); argtypes = [[[_tail cdr] cdr] car]; _argc = [argtypes length]; _argumentTypes = malloc (_argc * sizeof (MLKForeignType)); while (argtypes) { _argumentTypes[i] = MLKForeignTypeWithTypeDesignator ([argtypes car]); argtypes = [argtypes cdr]; } return self; } @end @implementation MLKLambdaForm -(id) complete { self = [super complete]; LASSIGN (_lambdaList, [_tail car]); // FIXME [NSException raise:@"MLKNotImplementedError" format:@"LAMBDA not yet implemented in the compiler"]; return self; } @end @implementation MLKFunctionForm +(Class) dispatchClassForObject:(id)object { id funname = [[object cdr] car]; if ([funname isKindOfClass:[MLKCons class]] && [funname car] == LAMBDA) return [MLKLambdaFunctionForm class]; else return [MLKSimpleFunctionForm class]; } @end @implementation MLKLambdaFunctionForm -(id) complete { self = [super complete]; LASSIGN (_lambdaForm, MAKE_FORM ([_tail car])); return self; } -(NSArray *) subforms { return [[super subforms] arrayByAddingObject:_lambdaForm]; } @end @implementation MLKSimpleFunctionForm -(id) complete { self = [super complete]; LASSIGN (_functionName, [_tail car]); return self; } @end @implementation MLKIfForm -(id) complete { self = [super complete]; LASSIGN (_conditionForm, MAKE_FORM ([_tail car])); LASSIGN (_consequentForm, MAKE_FORM ([[_tail cdr] car])); LASSIGN (_alternativeForm, MAKE_FORM ([[[_tail cdr] cdr] car])); return self; } -(NSArray *) subforms { return [[[[super subforms] arrayByAddingObject:_conditionForm] arrayByAddingObject:_consequentForm] arrayByAddingObject:_alternativeForm]; } @end @implementation MLKInPackageForm -(id) complete { self = [super complete]; LASSIGN (_packageDesignator, [_tail car]); return self; } @end @implementation MLKSimpleLambdaForm -(id) complete { MLKLexicalContext *newContext; self = [super complete]; LASSIGN (_lambdaListName, [_tail car]); newContext = [MLKLexicalContext contextWithParent:_context variables:[NSSet setWithObject:_lambdaListName] functions:nil goTags:nil macros:nil compilerMacros:nil symbolMacros:nil declarations:[self declarationsWithForms:[_tail cdr]]]; [self processBody:[_tail cdr] inContext:newContext]; return self; } -(MLKSymbol *) lambdaListName { return _lambdaListName; } @end @implementation MLKSimpleMacroletForm -(id) initWithObject:(id)object inContext:(MLKLexicalContext *)context forCompiler:(id)compiler { MLKLexicalContext *newContext; MLKForm *newForm; NSMutableDictionary *macros; id bindings; macros = [NSMutableDictionary dictionary]; bindings = [_tail car]; while (bindings) { id macro; macro = [_compiler compile:[MLKCons cons:_LAMBDA with:[[bindings car] cdr]] inContext:_context]; [macros setObject:macro forKey:nullify ([[bindings car] car])]; bindings = [bindings cdr]; } newContext = [MLKLexicalContext contextWithParent:_context variables:nil functions:nil goTags:nil macros:macros compilerMacros:nil symbolMacros:nil declarations:[self declarationsWithForms:[_tail cdr]]]; newForm = [MLKForm formWithObject:[MLKCons cons:LET with:[MLKCons cons:nil with:[_tail cdr]]] inContext:newContext forCompiler:_compiler]; LRELEASE (self); //?FIXME return LRETAIN (newForm); } @end @implementation MLKSimpleFletForm -(id) complete { NSMutableArray *bindingForms; MLKCons *bindings; NSMutableSet *functions; MLKLexicalContext *newContext; self = [super complete]; bindingForms = [NSMutableArray array]; functions = [NSMutableSet set]; bindings = [_tail car]; while (bindings) { [bindingForms addObject:[MLKSimpleFunctionBindingForm formWithObject:[bindings car] inContext:_context forCompiler:_compiler]]; [functions addObject:[[bindings car] car]]; bindings = [bindings cdr]; } newContext = [MLKLexicalContext contextWithParent:_context variables:nil functions:functions goTags:nil macros:nil compilerMacros:nil symbolMacros:nil declarations:[self declarationsWithForms:[[_tail cdr] cdr]]]; LASSIGN (_functionBindingForms, bindingForms); [self processBody:[_tail cdr] inContext:newContext]; return self; } -(NSArray *) subforms { return [[super subforms] arrayByAddingObjectsFromArray:_functionBindingForms]; } @end @implementation MLKLetForm -(id) complete { NSMutableArray *bindingForms; MLKCons *bindings; NSMutableSet *variables; MLKLexicalContext *newContext; self = [super complete]; bindingForms = [NSMutableArray array]; variables = [NSMutableSet set]; bindings = [_tail car]; while (bindings) { [bindingForms addObject:[MLKVariableBindingForm formWithObject:[bindings car] inContext:_context forCompiler:_compiler]]; [variables addObject:[[bindings car] car]]; bindings = [bindings cdr]; } newContext = [MLKLexicalContext contextWithParent:_context variables:variables functions:nil goTags:nil macros:nil compilerMacros:nil symbolMacros:nil declarations:[self declarationsWithForms:[[_tail cdr] cdr]]]; LASSIGN (_variableBindingForms, bindingForms); [self processBody:[_tail cdr] inContext:newContext]; return self; } -(NSArray *) subforms { return [[super subforms] arrayByAddingObjectsFromArray:_variableBindingForms]; } @end @implementation MLKLocallyForm -(id) complete { MLKLexicalContext *newContext; self = [super complete]; newContext = [MLKLexicalContext contextWithParent:_context variables:nil functions:nil goTags:nil macros:nil compilerMacros:nil symbolMacros:nil declarations:[self declarationsWithForms:[[_tail cdr] cdr]]]; [self processBody:[_tail cdr]]; return self; } @end @implementation MLKSimpleLoopForm -(id) complete { self = [super complete]; [self processBody:_tail]; return self; } @end @implementation MLKMultipleValueCallForm -(id) complete { self = [super complete]; LASSIGN (_functionForm, [_tail car]); [self processBody:[_tail cdr]]; return self; } -(NSArray *) subforms { return [[super subforms] arrayByAddingObject:_functionForm]; } @end @implementation MLKProgNForm -(id) complete { self = [super complete]; [self processBody:_tail]; return self; } @end @implementation MLKProgVForm -(id) complete { self = [super complete]; LASSIGN (_variableListForm, MAKE_FORM ([_tail car])); LASSIGN (_valueListForm, MAKE_FORM ([[_tail cdr] car])); [self processBody:[[_tail cdr] cdr]]; return self; } -(NSArray *) subforms { return [[[super subforms] arrayByAddingObject:_variableListForm] arrayByAddingObject:_valueListForm]; } @end @implementation MLKQuoteForm -(id) complete { self = [super complete]; LASSIGN (_quotedData, [_tail car]); return self; } @end @implementation MLKSetQForm -(id) complete { id rest; NSMutableArray *variables, *valueForms; self = [super complete]; rest = _tail; variables = [NSMutableArray array]; valueForms = [NSMutableArray array]; while (rest) { [variables addObject:nullify([rest car])]; [valueForms addObject:MAKE_FORM([[rest cdr] car])]; rest = [[rest cdr] cdr]; } LASSIGN (_variables, variables); LASSIGN (_valueForms, valueForms); return self; } -(NSArray *) subforms { return [[super subforms] arrayByAddingObjectsFromArray:_valueForms]; } @end @implementation MLKFSetQForm -(id) complete { id rest; NSMutableArray *functionNames, *valueForms; self = [super complete]; rest = _tail; functionNames = [NSMutableArray array]; valueForms = [NSMutableArray array]; while (rest) { [functionNames addObject:nullify([rest car])]; [valueForms addObject:MAKE_FORM([[rest cdr] car])]; rest = [[rest cdr] cdr]; } LASSIGN (_functionNames, functionNames); LASSIGN (_valueForms, valueForms); return self; } -(NSArray *) subforms { return [[super subforms] arrayByAddingObjectsFromArray:_valueForms]; } @end @implementation MLKThrowForm -(id) complete { self = [super complete]; LASSIGN (_tagForm, MAKE_FORM ([_tail car])); LASSIGN (_valueForm, MAKE_FORM ([[_tail cdr] car])); return self; } -(NSArray *) subforms { return [[[super subforms] arrayByAddingObject:_tagForm] arrayByAddingObject:_valueForm]; } @end @implementation MLKUnwindProtectForm -(id) complete { self = [super complete]; LASSIGN (_protectedForm, MAKE_FORM ([_tail car])); [self processBody:[_tail cdr]]; return self; } -(NSArray *) subforms { return [[super subforms] arrayByAddingObject:_protectedForm]; } @end @implementation MLKSimpleFunctionBindingForm +(Class) dispatchClassForObject:(id)object { return self; } -(id) complete { MLKLexicalContext *newContext; self = [super complete]; LASSIGN (_name, _head); LASSIGN (_lambdaListName, [_tail car]); newContext = [MLKLexicalContext contextWithParent:_context variables:[NSSet setWithObject:_lambdaListName] functions:nil goTags:nil macros:nil compilerMacros:nil symbolMacros:nil declarations:[self declarationsWithForms:[_tail cdr]]]; [self processBody:[_tail cdr] inContext:newContext]; return self; } -(id) name { return _name; } -(id) lambdaListName { return _lambdaListName; } -(id) bodyForms { return _bodyForms; } @end @implementation MLKVariableBindingForm +(Class) dispatchClassForObject:(id)object { return self; } -(id) complete { self = [super complete]; if ([_form isKindOfClass:[MLKCons class]]) { LASSIGN (_name, [_form car]); LASSIGN (_valueForm, MAKE_FORM ([[_form cdr] car])); } else { LASSIGN (_name, _form); LASSIGN (_valueForm, MAKE_FORM (nil)); } return self; } -(NSArray *) subforms { return [[super subforms] arrayByAddingObject:_valueForm]; } -(id) name { return _name; } -(id) valueForm { return _valueForm; } @end @implementation MLKDeclarationForm : MLKCompoundForm +(Class) dispatchClassForObject:(id)object { return self; } -(id) complete { self = [super complete]; LASSIGN (_type, [_form car]); LASSIGN (_arguments, [_form cdr] ? (id)[[_form cdr] array] : (id)[NSArray array]); return self; } @end