//
//  TLFunc.h
//  TinyLisp
//
//  Created by David Phillip Oster on 9/2/07.
//
//  Copyright 2007 David Phillip Oster

//     Licensed under the Apache License, Version 2.0 (the "License");
//     you may not use this file except in compliance with the License.
//     You may obtain a copy of the License at

//         http://www.apache.org/licenses/LICENSE-2.0

//     Unless required by applicable law or agreed to in writing, software
//     distributed under the License is distributed on an "AS IS" BASIS,
//     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//     See the License for the specific language governing permissions and
//     limitations under the License.
#import "TLTypes.h"

// evaluate the first element: 5 cases:
// builtin special function: hand the list to it as an argument.
// builtin function: evaluate each item in the list and hand it to the build in
// foriegn function: evaluate each item in the list and hand it to foriegn function
// is interpreted function: interpreter push a symbol table on the symbol table 
// stack lambda binding the arguments, and evaluates the body.
// first element doesn't evaluate to a function. just return it


@interface TLFuncAbstract : TLID {

}
+ (TLID *)tlApply:(NSArray *)call;
+ (NSArray *)evaluateArgs:(NSArray *)call;

+ (BOOL)isLambdaCall:(TLID *)first withArray:(NSArray *)call;
+ (TLID *)performLambdaCall:(TLID *)first withArray:(NSArray *)call;

+ (BOOL)isObjectiveCCall:(TLID *)first withArray:(NSArray *)call;
+ (TLID *)performObjectiveCCall:(TLID *)first withArray:(NSArray *)call;

@end

@interface TLFuncSpecial : TLFuncAbstract
+ (NSArray *)evaluateArgs:(NSArray *)call;
@end

@interface TLFunc : TLFuncAbstract
+ (NSArray *)evaluateArgs:(NSArray *)call;
@end

// (progn 1 2 3) evaluates its arguments, returns last one
@interface TLFuncprogn : TLFunc
@end

// (progn 1 2 3) evaluates its arguments, returns first one
@interface TLFuncprog0 : TLFunc
@end

// ' (+ 1 1 2 3) returns its argument, unevaluated
@interface TLFuncquote : TLFuncSpecial
@end

// (perform (perform (perform (class "NSNumber") "alloc") "initWithInt:" 1000) "autorelease")
// (perform (class "NSNumber") "numberWithInt:" 1000)
@interface TLFuncClassFromString : TLFunc
@end

// (performSelector 'anArray "objectForIndex:" 0) 
// 
@interface TLFuncPerformSelector : TLFunc
@end


// (set 'a (+ 1 2)) evalauates its aguments, 
// sets the second argument as the value of the first
@interface TLFuncset : TLFunc
@end

// (if e s) if expression 'e' evaluates to non-nil, evaluate s.
// (if e s1 s2) if expression 'e' evaluates to non-nil, evaluate s1, else evaluate s2
@interface TLFunctlIf : TLFuncSpecial
@end

// (while e s) while expression 'e' evaluates non-nil, evaluate s
@interface TLFunctlWhile : TLFuncSpecial
@end

// (and e1 e2) like '&&' in C: evaluate as long as subexpressons are true
@interface TLFunctlAnd : TLFuncSpecial
@end

// (or e1 e2) like '||' in C: evaluate as long as subexpressons are false
@interface TLFunctlOr : TLFuncSpecial
@end

// (+ e1 e2 e3) sum of the subexpressions.
@interface TLFuncplus : TLFunc
@end

// (- e1 e2) returns e1 - e2
// (- e1) returns -e1
@interface TLFuncminus : TLFunc
@end

// (* e1 e2 e3) product of the subexpressions.
@interface TLFunctimes : TLFunc
@end

// (/ e1 e2) returns e1 / e2
// (/ e1) returns 1./e1
@interface TLFuncdivide : TLFunc
@end

// (= e1 e2) returns e1 isEqual: e2
@interface TLFunceq : TLFunc
@end

// (> e1 e2) returns e1 > e2
@interface TLFuncgt : TLFunc
@end


// (< e1 e2) returns e1 < e2
@interface TLFunclt : TLFunc
@end


// (>= e1 e2) returns e1 >= e2
@interface TLFuncge : TLFunc
@end


// (<= e1 e2) returns e1 <= e2
@interface TLFuncle : TLFunc
@end

@interface TLFuncprint : TLFunc
@end

@interface TLFunccount : TLFunc
@end

// (list 2 3 4) returns (2 3 4)
@interface TLFunclist : TLFunc
@end

// objectAtIndex = at
@interface TLFuncAtIndex : TLFunc
@end

// insertAtIndex
@interface TLFuncInsertAtIndex : TLFunc
@end

// removeAtIndex
@interface TLFuncRemoveAtIndex : TLFunc
@end

// replaceAtIndex
@interface TLFuncReplaceAtIndexWith : TLFunc
@end

// (propertyForKey 'a "foo")
@interface TLFuncPropertyForKey : TLFunc
@end

// (removePropertyForKey 'a "foo")
@interface TLFuncRemovePropertyForKey : TLFunc
@end

// (setPropertyForKey 'a 5 "foo")
@interface TLFuncSetPropertyForKey : TLFunc
@end

// (propertyKeys 'a)
@interface TLFuncPropertyKeys : TLFunc
@end

