summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--GNUmakefile4
-rw-r--r--MLKInterpreter.m32
-rw-r--r--MLKPackage.m6
-rw-r--r--MLKRoot.h30
-rw-r--r--MLKRoot.m131
5 files changed, 197 insertions, 6 deletions
diff --git a/GNUmakefile b/GNUmakefile
index 51673aa..997c23b 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -33,8 +33,8 @@ ToiletKit_OBJC_FILES = MLKCharacter.m MLKCons.m MLKBinding.m \
MLKLexicalContext.m MLKLexicalEnvironment.m \
MLKLispValue.m MLKPackage.m MLKParenReader.m \
MLKRatio.m MLKReader.m MLKReadtable.m \
- MLKReaderError.m MLKSingleFloat.m MLKStream.m \
- MLKStringInputStream.m MLKSymbol.m \
+ MLKReaderError.m MLKRoot.m MLKSingleFloat.m \
+ MLKStream.m MLKStringInputStream.m MLKSymbol.m \
MLKThrowException.m NSObject-MLKPrinting.m \
NSString-MLKPrinting.m
ToiletKit_LDFLAGS = -lgmp
diff --git a/MLKInterpreter.m b/MLKInterpreter.m
index 49db342..35ea2ad 100644
--- a/MLKInterpreter.m
+++ b/MLKInterpreter.m
@@ -25,6 +25,7 @@
#import "MLKLexicalContext.h"
#import "MLKLexicalEnvironment.h"
#import "MLKPackage.h"
+#import "MLKRoot.h"
#import "MLKSymbol.h"
#import "runtime-compatibility.h"
@@ -376,10 +377,33 @@ static MLKSymbol *_LAMBDA;
}
else
{
- [NSException raise:@"MLKNoSuchOperatorException"
- format:@"%@ does not name a known operator.",
- [car descriptionForLisp]];
- return nil;
+ NSMutableArray *args = [NSMutableArray array];
+ MLKCons *rest = [program cdr];
+ NSArray *results;
+
+ while (rest)
+ {
+ id result = [[self eval:[rest car]
+ inLexicalContext:context
+ withEnvironment:lexenv]
+ objectAtIndex:0];
+ [args addObject:result];
+ rest = [rest cdr];
+ }
+
+ results = [MLKRoot dispatch:car withArguments:args];
+
+ if (results)
+ {
+ return results;
+ }
+ else
+ {
+ [NSException raise:@"MLKNoSuchOperatorException"
+ format:@"%@ does not name a known operator.",
+ [car descriptionForLisp]];
+ return nil;
+ }
}
}
}
diff --git a/MLKPackage.m b/MLKPackage.m
index b8370c4..117ff94 100644
--- a/MLKPackage.m
+++ b/MLKPackage.m
@@ -76,6 +76,12 @@ static NSMutableDictionary *packages = nil;
[sys export:[sys intern:@"%DEFMACRO"]];
[sys export:[sys intern:@"%LAMBDA"]];
+
+ [sys export:[sys intern:@"CAR"]];
+ [sys export:[sys intern:@"CDR"]];
+ [sys export:[sys intern:@"SET-CAR"]];
+ [sys export:[sys intern:@"SET-CDR"]];
+ [sys export:[sys intern:@"CONS"]];
[tlUser usePackage:clUser];
}
diff --git a/MLKRoot.h b/MLKRoot.h
new file mode 100644
index 0000000..0eec36d
--- /dev/null
+++ b/MLKRoot.h
@@ -0,0 +1,30 @@
+/* -*- mode: objc; coding: utf-8 -*- */
+/* Étoilisp/Mulklisp, 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 "runtime-compatibility.h"
+
+#import <Foundation/NSArray.h>
+#import <Foundation/NSObject.h>
+
+
+@interface MLKRoot : NSObject
++(void) initialize;
+
++(NSArray *) dispatch:(MLKSymbol *)name withArguments:(NSArray *)args;
+@end
diff --git a/MLKRoot.m b/MLKRoot.m
new file mode 100644
index 0000000..4492b7b
--- /dev/null
+++ b/MLKRoot.m
@@ -0,0 +1,131 @@
+/* -*- mode: objc; coding: utf-8 -*- */
+/* Étoilisp/Mulklisp, 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 "MLKPackage.h"
+#import "MLKRoot.h"
+#import "MLKSymbol.h"
+#import "runtime-compatibility.h"
+
+#import <Foundation/NSArray.h>
+#import <Foundation/NSException.h>
+#import <Foundation/NSInvocation.h>
+#import <Foundation/NSMethodSignature.h>
+#import <Foundation/NSNull.h>
+#import <Foundation/NSString.h>
+
+
+static id nullify (id value)
+{
+ if (value)
+ return value;
+ else
+ return [NSNull null];
+}
+
+static id denullify (id value)
+{
+ if (value == [NSNull null])
+ return nil;
+ else
+ return value;
+}
+
+
+static NSMethodSignature *signature;
+static MLKPackage *sys;
+
+
+@implementation MLKRoot
++(void) initialize
+{
+ signature = RETAIN ([self methodSignatureForSelector:@selector(car:)]);
+ sys = [MLKPackage findPackage:@"TOILET-SYSTEM"];
+}
+
++(NSArray *) dispatch:(MLKSymbol *)name withArguments:(NSArray *)args
+{
+ NSInvocation *invocation;
+ NSMutableString *methodName;
+ NSArray *result;
+ SEL selector;
+
+ NS_DURING
+ {
+ if ([sys findSymbol:[name name]] != name)
+ return nil;
+ }
+ NS_HANDLER
+ {
+ NS_VALUERETURN (nil, NSArray *);
+ }
+ NS_ENDHANDLER
+
+ invocation = [NSInvocation invocationWithMethodSignature:signature];
+
+ methodName = [NSMutableString stringWithString:[[name name] lowercaseString]];
+ [methodName replaceOccurrencesOfString:@"-"
+ withString:@"_"
+ options:NSLiteralSearch
+ range:NSMakeRange(0, [methodName length])];
+ [methodName appendString:@":"];
+
+ selector = NSSelectorFromString (methodName);
+
+ if (!selector || ![self respondsToSelector:selector])
+ return nil;
+
+ [invocation setSelector:selector];
+ [invocation setTarget:self];
+ [invocation setArgument:&args atIndex:2];
+
+ [invocation invoke];
+ [invocation getReturnValue:&result];
+
+ return result;
+}
+
++(NSArray *) car:(NSArray *)args
+{
+ return [NSArray arrayWithObject:nullify([denullify([args objectAtIndex:0]) car])];
+}
+
++(NSArray *) cdr:(NSArray *)args
+{
+ return [NSArray arrayWithObject:nullify([denullify([args objectAtIndex:0]) cdr])];
+}
+
++(NSArray *) set_car:(NSArray *)args
+{
+ [[args objectAtIndex:0] setCar:denullify([args objectAtIndex:1])];
+ return [NSArray arrayWithObject:[args objectAtIndex:1]];
+}
+
++(NSArray *) set_cdr:(NSArray *)args
+{
+ [[args objectAtIndex:0] setCdr:denullify([args objectAtIndex:1])];
+ return [NSArray arrayWithObject:[args objectAtIndex:1]];
+}
+
++(NSArray *) cons:(NSArray *)args
+{
+ return [NSArray arrayWithObject:
+ [MLKCons cons:denullify([args objectAtIndex:0])
+ with:denullify([args objectAtIndex:1])]];
+}
+@end