summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--GNUmakefile8
-rw-r--r--MLKCons.h4
-rw-r--r--MLKCons.m15
-rw-r--r--MLKDynamicContext.h2
-rw-r--r--MLKDynamicContext.m15
-rw-r--r--MLKInterpreter.h30
-rw-r--r--MLKInterpreter.m146
-rw-r--r--MLKLexicalContext.h54
8 files changed, 270 insertions, 4 deletions
diff --git a/GNUmakefile b/GNUmakefile
index 3bdc97a..b001940 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -25,10 +25,10 @@ FRAMEWORK_NAME = ToiletKit
ToiletKit_OBJC_FILES = MLKCharacter.m MLKCons.m MLKDoubleFloat.m \
MLKDynamicContext.m MLKEndOfFileError.m \
MLKEnvironment.m MLKError.m MLKFloat.m \
- MLKInteger.m MLKLinkedList.m MLKLispValue.m \
- MLKPackage.m MLKParenReader.m MLKRatio.m \
- MLKReader.m MLKReadtable.m MLKReaderError.m \
- MLKSingleFloat.m MLKStream.m \
+ MLKInteger.m MLKInterpreter.m MLKLinkedList.m \
+ MLKLispValue.m MLKPackage.m MLKParenReader.m \
+ MLKRatio.m MLKReader.m MLKReadtable.m \
+ MLKReaderError.m MLKSingleFloat.m MLKStream.m \
MLKStringInputStream.m MLKSymbol.m \
MLKThrowException.m \
MLKUndefinedVariableException.m \
diff --git a/MLKCons.h b/MLKCons.h
index d343e3f..a93e3d2 100644
--- a/MLKCons.h
+++ b/MLKCons.h
@@ -18,6 +18,8 @@
#import "MLKLispValue.h"
+@class NSArray;
+
@interface MLKCons : MLKLispValue
{
@@ -34,6 +36,8 @@
-(void) setCar:(id)value;
-(void) setCdr:(id)value;
+-(NSArray *)array;
+
-(NSString *)bareDescriptionForLisp; // description without
// parentheses, for internal use
// only
diff --git a/MLKCons.m b/MLKCons.m
index 969060e..b2b3b8b 100644
--- a/MLKCons.m
+++ b/MLKCons.m
@@ -19,6 +19,7 @@
#import "MLKCons.h"
#import "runtime-compatibility.h"
+#import <Foundation/NSArray.h>
#import <Foundation/NSString.h>
@@ -57,6 +58,20 @@
ASSIGN (_cdr, value);
}
+-(NSArray *)array
+{
+ NSMutableArray *array = [NSMutableArray array];
+ id rest = self;
+
+ while (rest)
+ {
+ [array addObject:[rest car]];
+ rest = [rest cdr];
+ }
+
+ return array;
+}
+
-(NSString *)bareDescriptionForLisp
{
if (!_cdr)
diff --git a/MLKDynamicContext.h b/MLKDynamicContext.h
index b4c304c..2c58483 100644
--- a/MLKDynamicContext.h
+++ b/MLKDynamicContext.h
@@ -16,6 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <Foundation/NSObject.h>
+
@class MLKEnvironment, MLKSymbol, NSLinkedList,
NSMutableDictionary, NSString;
diff --git a/MLKDynamicContext.m b/MLKDynamicContext.m
index 87a88cc..83359cb 100644
--- a/MLKDynamicContext.m
+++ b/MLKDynamicContext.m
@@ -59,12 +59,27 @@ static MLKDynamicContext *global_context;
nicknames:[NSSet setWithObject:@"CL-USER"]];
MLKPackage *keyword = [MLKPackage packageWithName:@"KEYWORD"
nicknames:[NSSet set]];
+ MLKPackage *sys = [MLKPackage packageWithName:@"TOILET-SYSTEM"
+ nicknames:[NSSet setWithObjects:
+ @"TL-SYS", nil]];
+ MLKPackage *toilet = [MLKPackage packageWithName:@"TOILET-LISP"
+ nicknames:[NSSet setWithObjects:
+ @"TL", @"TOILET", nil]];
+ MLKPackage *tlUser = [MLKPackage packageWithName:@"TOILET-LISP-USER"
+ nicknames:[NSSet setWithObjects:
+ @"TL-USER",
+ @"TOILET-USER",
+ nil]];
MLKSymbol *t = [cl intern:@"T"];
MLKReadtable *readtable = [[MLKReadtable alloc] init];
unichar ch;
id NIL = [NSNull null];
+ [sys intern:@"%DEFMACRO"];
+ [tlUser usePackage:clUser];
+ [toilet import:nil];
+
// Build the initial readtable.
[readtable setSyntaxType:WHITESPACE forCharacter:'\t'];
[readtable setConstituentTrait:INVALID forCharacter:'\t'];
diff --git a/MLKInterpreter.h b/MLKInterpreter.h
new file mode 100644
index 0000000..1129c83
--- /dev/null
+++ b/MLKInterpreter.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 <Foundation/NSObject.h>
+
+@class MLKLexicalContext, MLKEnvironment;
+
+
+@interface MLKInterpreter : NSObject
++(void) initialize;
+
++(id) eval:(id)program
+ inLexicalContext:(MLKLexicalContext *)context
+ withEnvironment:(MLKEnvironment *)lexenv;
+@end
diff --git a/MLKInterpreter.m b/MLKInterpreter.m
new file mode 100644
index 0000000..37da36d
--- /dev/null
+++ b/MLKInterpreter.m
@@ -0,0 +1,146 @@
+/* -*- 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 "MLKDynamicContext.h"
+#import "MLKEnvironment.h"
+#import "MLKFuncallable.h"
+#import "MLKInterpreter.h"
+#import "MLKLexicalContext.h"
+#import "MLKPackage.h"
+#import "MLKSymbol.h"
+#import "runtime-compatibility.h"
+
+#import <Foundation/NSArray.h>
+#import <Foundation/NSString.h>
+
+
+static MLKPackage *cl;
+static MLKPackage *sys;
+static MLKSymbol *IF;
+static MLKSymbol *PROGN;
+static MLKSymbol *TAGBODY;
+static MLKSymbol *GO;
+static MLKSymbol *CATCH;
+static MLKSymbol *THROW;
+static MLKSymbol *LAMBDA;
+static MLKSymbol *LET;
+static MLKSymbol *APPLY;
+static MLKSymbol *FUNCALL;
+static MLKSymbol *EVAL;
+static MLKSymbol *_DEFMACRO;
+
+
+@implementation MLKInterpreter
++(void) initialize
+{
+ cl = [MLKPackage findPackage:@"COMMON-LISP"];
+ sys = [MLKPackage findPackage:@"TOILET-SYSTEM"];
+
+ IF = [cl intern:@"IF"];
+ 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"];
+ APPLY = [cl intern:@"APPLY"];
+ EVAL = [cl intern:@"EVAL"];
+ _DEFMACRO = [sys intern:@"%DEFMACRO"];
+}
+
+
++(id) eval:(id)program
+ inLexicalContext:(MLKLexicalContext *)context
+ withEnvironment:(MLKEnvironment *)lexenv
+{
+ MLKDynamicContext *dynamicContext = [MLKDynamicContext currentContext];
+
+ if (!program || [program isKindOfClass:[MLKSymbol class]])
+ {
+ if ([context variableIsLexical:program])
+ {
+ return [lexenv valueForBinding:program];
+ }
+ else
+ {
+ return [dynamicContext valueForBinding:program];
+ }
+ }
+ else if (![program isKindOfClass:[MLKCons class]])
+ {
+ // Everything that is not a list or a symbol evaluates to itself.
+ return program;
+ }
+ else
+ {
+ id car = [program car];
+
+ if ([car isKindOfClass:[MLKSymbol class]])
+ {
+ if (car == APPLY)
+ {
+ MLKCons *rest = [self eval:[[[program cdr] cdr] car]
+ inLexicalContext:context
+ withEnvironment:lexenv];
+
+ return [[[program cdr] car] applyToArray:(rest
+ ? [rest array]
+ : [NSArray array])];
+ }
+ else if (car == EVAL)
+ {
+ return [self eval:[self eval:[program cdr]
+ inLexicalContext:context
+ withEnvironment:lexenv]
+ inLexicalContext:[MLKLexicalContext nullContext]
+ withEnvironment:
+ AUTORELEASE([[MLKEnvironment alloc] init])];
+ }
+ else if (car == PROGN)
+ {
+ id result;
+ id rest = program;
+ while ((rest = [rest cdr]))
+ {
+ result = [self eval:[rest car]
+ inLexicalContext:context
+ withEnvironment:lexenv];
+ }
+
+ return result;
+ }
+ else if (car == TAGBODY)
+ {
+ //FIXME: ...
+ }
+ else
+ {
+ //FIXME: ...
+ }
+ }
+ else if (![car isKindOfClass:[MLKCons class]] && [car car] == LAMBDA)
+ {
+ return [self eval:[MLKCons cons:FUNCALL with:program]
+ inLexicalContext:context
+ withEnvironment:lexenv];
+ }
+ }
+}
+@end
diff --git a/MLKLexicalContext.h b/MLKLexicalContext.h
new file mode 100644
index 0000000..a93e40f
--- /dev/null
+++ b/MLKLexicalContext.h
@@ -0,0 +1,54 @@
+/* -*- 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 "MLKLispValue.h"
+
+@class MLKEnvironment, MLKSymbol, NSLinkedList, NSSet,
+ NSMutableDictionary, NSString, MLKCons;
+
+
+@interface MLKLexicalContext : MLKLispValue
+{
+ MLKEnvironment *_macroBindings;
+ MLKEnvironment *_goTags;
+ NSMutableDictionary *_variableLocations;
+ MLKCons *_declarations;
+ MLKLexicalContext *_parent;
+}
+
+-(MLKLexicalContext *) initWithParent:(MLKLexicalContext *)aContext
+ variables:(NSSet *)vars
+ goTags:(NSDictionary *)goTags
+ macros:(NSDictionary *)macros
+ declarations:(NSDictionary *)declarations;
+
++(MLKLexicalContext *) globalContext;
++(MLKLexicalContext *) nullContext;
+
+-(MLKEnvironment *) environment;
+
+-(id) macroForSymbol:(MLKSymbol *)symbol;
+-(id) goTagForSymbol:(MLKSymbol *)symbol;
+-(id) variableLocationForSymbol:(MLKSymbol *)symbol;
+
+-(void) addVariable:(MLKSymbol *)symbol;
+
+-(BOOL) variableIsLexical:(MLKSymbol *)symbol;
+
+-(void) dealloc;
+@end