diff options
author | Matthias Andreas Benkard <matthias@benkard.de> | 2008-08-10 12:17:53 +0200 |
---|---|---|
committer | Matthias Andreas Benkard <matthias@benkard.de> | 2008-08-10 12:17:53 +0200 |
commit | c802172ab92da89a8e9a8cc92c47c09f222dacd1 (patch) | |
tree | c1e4588297c27c8d268594b5a2621e61a4cc7e0b | |
parent | ddf78cc594ae390a8bfff95555dc285c1bbd28f5 (diff) |
Add class cluster MLKForm.
-rw-r--r-- | GNUmakefile | 2 | ||||
-rw-r--r-- | MLKForm.m | 209 | ||||
-rw-r--r-- | MLKInterpreter.m | 90 | ||||
-rw-r--r-- | special-symbols.h | 114 |
4 files changed, 326 insertions, 89 deletions
diff --git a/GNUmakefile b/GNUmakefile index cff81a7..3f7ae93 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -53,7 +53,7 @@ ToiletKit_OBJC_FILES = functions.m globals.m MLKArray.m \ MLKDoubleFloat.m \ MLKDispatchingMacroCharacterReader.m \ MLKDynamicContext.m MLKEnvironment.m MLKFloat.m \ - MLKForeignProcedure.m MLKInteger.m \ + MLKForeignProcedure.m MLKForm.m MLKInteger.m \ MLKInterpretedClosure.m MLKInterpreter.m \ MLKLexicalContext.m MLKLexicalEnvironment.m \ MLKLispValue.m MLKNumber.m MLKPackage.m \ diff --git a/MLKForm.m b/MLKForm.m new file mode 100644 index 0000000..6e8bed5 --- /dev/null +++ b/MLKForm.m @@ -0,0 +1,209 @@ +/* -*- 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 <http://www.gnu.org/licenses/>. + */ + +#import "MLKCons.h" +#import "MLKForm.h" +#import "util.h" +#import "special-symbols.h" + +#import <Foundation/NSString.h> + + +@implementation MLKForm +-(void) initialize +{ + ensure_symbols (); +} + +-(id) initWithObject:(id)object + inContext:(MLKLexicalContext *)context + forCompiler:(id)compiler +{ + _form = object; + _context = context; + _compiler = compiler; + return [self complete]; +} + +-(id) complete +{ + return self; +} + ++(Class) dispatchClassForObject:(id)object +{ + if ([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]); +} +@end + + +@implementation MLKAtomicForm ++(Class) dispatchClassForObject:(id)object +{ + if ([object isKindOfClass:[MLKSymbol class]]) + return [MLKSymbolForm class]; + else + return [MLKSelfEvaluatingForm class]; +} +@end + + +@implementation MLKSelfEvaluatingForm +// FIXME + ++(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 == APPLY) return [MLKFunctionCallForm class]; + else if (car == CATCH) return [MLKCatchForm class]; + else if (car == _DEFMACRO) return [MLKSimpleDefmacroForm 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 == SET) return [MLKSetForm class]; + else if (car == _FSET) return [MLKFSetForm 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 ([_head isKindOfClass:[MLKCons class]]) + { + LRELEASE (self); + return [MLKForm formWithObject:[MLKCons cons:FUNCALL + with:object] + inContext:context + forCompiler:compiler]; + } + else if ([context symbolNamesMacro:_head]) + { + LRELEASE (self); + return [MLKMacroCallForm formWithObject:object + inContext:context + forCompiler:compiler]; + } + else + { + LRELEASE (self); + return [MLKFunctionCallForm formWithObject:object + inContext:context + forCompiler:compiler]; + } +} + + ++(Class) dispatchClassForObject:(id)object +{ + return self; +} +@end + + +@implementation MLKMacroCallForm : MLKSimpleCompoundForm +-(id) initWithObject:(id)object + inContext:(MLKLexicalContext *)context + forCompiler:(id)compiler +{ + self = [super initWithObject:object + inContext:context + forCompiler:compiler]; + + id <MLKFuncallable> macrofun = [context macroForSymbol:_head]; + id expansion = denullify ([[macrofun + applyToArray: + [NSArray arrayWithObjects: + _form, context, nil]] + objectAtIndex:0]); + + return [MLKForm formWithObject:expansion + inContext:context + forCompiler:compiler]; +} +@end diff --git a/MLKInterpreter.m b/MLKInterpreter.m index deb92eb..d3d6161 100644 --- a/MLKInterpreter.m +++ b/MLKInterpreter.m @@ -35,6 +35,7 @@ #import "MLKSymbol.h" #import "NSObject-MLKPrinting.h" #import "runtime-compatibility.h" +#import "special-symbols.h" #import "util.h" #import <Foundation/NSArray.h> @@ -56,97 +57,10 @@ #endif -static MLKPackage *cl; -static MLKPackage *sys; -static MLKPackage *keyword; -static MLKSymbol *IF; -static MLKSymbol *IN_PACKAGE; -static MLKSymbol *DECLARE; -static MLKSymbol *PROGN; -static MLKSymbol *TAGBODY; -static MLKSymbol *GO; -static MLKSymbol *CATCH; -static MLKSymbol *THROW; -static MLKSymbol *_FLET; -static MLKSymbol *_MACROLET; -static MLKSymbol *LAMBDA; -static MLKSymbol *LET; -static MLKSymbol *LOCALLY; -static MLKSymbol *APPLY; -static MLKSymbol *FUNCALL; -static MLKSymbol *FUNCTION; -static MLKSymbol *EVAL; -static MLKSymbol *EVAL_WHEN; -static MLKSymbol *QUOTE; -static MLKSymbol *SETQ; -static MLKSymbol *SETF; -static MLKSymbol *SET; -static MLKSymbol *_FSETQ; -static MLKSymbol *_FSET; -static MLKSymbol *SYMBOL_MACROLET; -static MLKSymbol *PROGV; -static MLKSymbol *UNWIND_PROTECT; -static MLKSymbol *VALUES; -static MLKSymbol *_DEFMACRO; -static MLKSymbol *_FOREIGN_LAMBDA; -static MLKSymbol *_LAMBDA; -static MLKSymbol *_LOOP; -static MLKSymbol *V_INITP; -static MLKSymbol *COMPILE_TOPLEVEL; -static MLKSymbol *COMPILE; -static MLKSymbol *LOAD_TOPLEVEL; -static MLKSymbol *LOAD; -static MLKSymbol *EXECUTE; -static MLKSymbol *MULTIPLE_VALUE_CALL; - - @implementation MLKInterpreter +(void) initialize { - cl = [MLKPackage findPackage:@"COMMON-LISP"]; - sys = [MLKPackage findPackage:@"TOILET-SYSTEM"]; - keyword = [MLKPackage findPackage:@"KEYWORD"]; - - IF = [cl intern:@"IF"]; - IN_PACKAGE = [cl intern:@"IN-PACKAGE"]; - DECLARE = [cl intern:@"DECLARE"]; - PROGN = [cl intern:@"PROGN"]; - TAGBODY = [cl intern:@"TAGBODY"]; - GO = [cl intern:@"GO"]; - CATCH = [cl intern:@"CATCH"]; - THROW = [cl intern:@"THROW"]; - LAMBDA = [cl intern:@"LAMBDA"]; - LET = [cl intern:@"LET"]; - LOCALLY = [cl intern:@"LOCALLY"]; - _FLET = [sys intern:@"%FLET"]; - _MACROLET = [sys intern:@"%MACROLET"]; - _LOOP = [sys intern:@"%LOOP"]; - APPLY = [cl intern:@"APPLY"]; - EVAL = [cl intern:@"EVAL"]; - EVAL_WHEN = [cl intern:@"EVAL-WHEN"]; - FUNCALL = [cl intern:@"FUNCALL"]; - FUNCTION = [cl intern:@"FUNCTION"]; - QUOTE = [cl intern:@"QUOTE"]; - SETQ = [cl intern:@"SETQ"]; - SETF = [cl intern:@"SETF"]; - SET = [cl intern:@"SET"]; - _FSETQ = [sys intern:@"%FSETQ"]; - _FSET = [sys intern:@"%FSET"]; - SYMBOL_MACROLET = [cl intern:@"SYMBOL-MACROLET"]; - PROGV = [cl intern:@"PROGV"]; - VALUES = [cl intern:@"VALUES"]; - UNWIND_PROTECT = [cl intern:@"UNWIND-PROTECT"]; - _DEFMACRO = [sys intern:@"%DEFMACRO"]; - _FOREIGN_LAMBDA = [sys intern:@"%FOREIGN-LAMBDA"]; - _LAMBDA = [sys intern:@"%LAMBDA"]; - V_INITP = [sys intern:@"*SYSTEM-INITIALISED-P*"]; - MULTIPLE_VALUE_CALL = [cl intern:@"MULTIPLE-VALUE-CALL"]; - - COMPILE_TOPLEVEL = [keyword intern:@"COMPILE-TOPLEVEL"]; - COMPILE = [cl intern:@"COMPILE"]; - LOAD_TOPLEVEL = [keyword intern:@"LOAD-TOPLEVEL"]; - LOAD = [cl intern:@"LOAD"]; - EXECUTE = [keyword intern:@"EXECUTE"]; + ensure_symbols (); } diff --git a/special-symbols.h b/special-symbols.h new file mode 100644 index 0000000..2e80bf7 --- /dev/null +++ b/special-symbols.h @@ -0,0 +1,114 @@ +/* -*- 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 <http://www.gnu.org/licenses/>. + */ + +#import "MLKSymbol.h" +#import "MLKPackage.h" + +static MLKPackage *cl; +static MLKPackage *sys; +static MLKPackage *keyword; + +static MLKSymbol *IF; +static MLKSymbol *IN_PACKAGE; +static MLKSymbol *DECLARE; +static MLKSymbol *PROGN; +static MLKSymbol *TAGBODY; +static MLKSymbol *GO; +static MLKSymbol *CATCH; +static MLKSymbol *THROW; +static MLKSymbol *_FLET; +static MLKSymbol *_MACROLET; +static MLKSymbol *LAMBDA; +static MLKSymbol *LET; +static MLKSymbol *LOCALLY; +static MLKSymbol *APPLY; +static MLKSymbol *FUNCALL; +static MLKSymbol *FUNCTION; +static MLKSymbol *EVAL; +static MLKSymbol *EVAL_WHEN; +static MLKSymbol *QUOTE; +static MLKSymbol *SETQ; +static MLKSymbol *SETF; +static MLKSymbol *SET; +static MLKSymbol *_FSETQ; +static MLKSymbol *_FSET; +static MLKSymbol *SYMBOL_MACROLET; +static MLKSymbol *PROGV; +static MLKSymbol *UNWIND_PROTECT; +static MLKSymbol *VALUES; +static MLKSymbol *_DEFMACRO; +static MLKSymbol *_FOREIGN_LAMBDA; +static MLKSymbol *_LAMBDA; +static MLKSymbol *_LOOP; +static MLKSymbol *V_INITP; +static MLKSymbol *COMPILE_TOPLEVEL; +static MLKSymbol *COMPILE; +static MLKSymbol *LOAD_TOPLEVEL; +static MLKSymbol *LOAD; +static MLKSymbol *EXECUTE; +static MLKSymbol *MULTIPLE_VALUE_CALL; + + +static void +ensure_symbols () +{ + cl = [MLKPackage findPackage:@"COMMON-LISP"]; + sys = [MLKPackage findPackage:@"TOILET-SYSTEM"]; + keyword = [MLKPackage findPackage:@"KEYWORD"]; + + IF = [cl intern:@"IF"]; + IN_PACKAGE = [cl intern:@"IN-PACKAGE"]; + DECLARE = [cl intern:@"DECLARE"]; + PROGN = [cl intern:@"PROGN"]; + TAGBODY = [cl intern:@"TAGBODY"]; + GO = [cl intern:@"GO"]; + CATCH = [cl intern:@"CATCH"]; + THROW = [cl intern:@"THROW"]; + LAMBDA = [cl intern:@"LAMBDA"]; + LET = [cl intern:@"LET"]; + LOCALLY = [cl intern:@"LOCALLY"]; + _FLET = [sys intern:@"%FLET"]; + _MACROLET = [sys intern:@"%MACROLET"]; + _LOOP = [sys intern:@"%LOOP"]; + APPLY = [cl intern:@"APPLY"]; + EVAL = [cl intern:@"EVAL"]; + EVAL_WHEN = [cl intern:@"EVAL-WHEN"]; + FUNCALL = [cl intern:@"FUNCALL"]; + FUNCTION = [cl intern:@"FUNCTION"]; + QUOTE = [cl intern:@"QUOTE"]; + SETQ = [cl intern:@"SETQ"]; + SETF = [cl intern:@"SETF"]; + SET = [cl intern:@"SET"]; + _FSETQ = [sys intern:@"%FSETQ"]; + _FSET = [sys intern:@"%FSET"]; + SYMBOL_MACROLET = [cl intern:@"SYMBOL-MACROLET"]; + PROGV = [cl intern:@"PROGV"]; + VALUES = [cl intern:@"VALUES"]; + UNWIND_PROTECT = [cl intern:@"UNWIND-PROTECT"]; + _DEFMACRO = [sys intern:@"%DEFMACRO"]; + _FOREIGN_LAMBDA = [sys intern:@"%FOREIGN-LAMBDA"]; + _LAMBDA = [sys intern:@"%LAMBDA"]; + V_INITP = [sys intern:@"*SYSTEM-INITIALISED-P*"]; + MULTIPLE_VALUE_CALL = [cl intern:@"MULTIPLE-VALUE-CALL"]; + + COMPILE_TOPLEVEL = [keyword intern:@"COMPILE-TOPLEVEL"]; + COMPILE = [cl intern:@"COMPILE"]; + LOAD_TOPLEVEL = [keyword intern:@"LOAD-TOPLEVEL"]; + LOAD = [cl intern:@"LOAD"]; + EXECUTE = [keyword intern:@"EXECUTE"]; +} |