//
//  EXPFunctionElement.m
//  XMLTest
//
//  Created by Ashley on 10/05/2007.
//  Copyright 2007 __MyCompanyName__. All rights reserved.
//

#import "EXPFunctionElement.h"
#import "EXPSymbolTable.h"
#import "EXPAssemblerConstants.h"

@implementation EXPFunctionElement

+ (void) registerFunction:(EXPSymbolTable *)table name:(NSString *)name opcode:(unsigned int)opcode variableArgs:(BOOL)vargs
{
	EXPFunctionElement *function = [[EXPFunctionElement alloc] init];
	[function setName:name];
	[function setAddress:opcode];
	[function setVariableArgs:vargs];
	[table declareSymbol:function];
	[function release];
}

+ (void) registerDefaultFunctions:(EXPSymbolTable *)table
{
	[EXPFunctionElement registerFunction:table name:@"abs"    opcode:ABSA   variableArgs:NO];
	[EXPFunctionElement registerFunction:table name:@"sqrt"   opcode:SQRTA  variableArgs:NO];   
	[EXPFunctionElement registerFunction:table name:@"int"    opcode:INTA   variableArgs:NO];   
	[EXPFunctionElement registerFunction:table name:@"exp"    opcode:EXPA   variableArgs:NO];   
	[EXPFunctionElement registerFunction:table name:@"log"    opcode:LNA    variableArgs:NO];   
	[EXPFunctionElement registerFunction:table name:@"log10"  opcode:LOG10A variableArgs:NO];  
	[EXPFunctionElement registerFunction:table name:@"sin"    opcode:SINA   variableArgs:NO];  
	[EXPFunctionElement registerFunction:table name:@"cos"    opcode:COSA   variableArgs:NO];
	[EXPFunctionElement registerFunction:table name:@"tan"    opcode:TANA   variableArgs:NO]; 
	[EXPFunctionElement registerFunction:table name:@"asin"   opcode:ASINA  variableArgs:NO];
	[EXPFunctionElement registerFunction:table name:@"acos"   opcode:ACOSA  variableArgs:NO];
	[EXPFunctionElement registerFunction:table name:@"atan"   opcode:ATANA  variableArgs:NO];
	[EXPFunctionElement registerFunction:table name:@"sinh"   opcode:SINHA  variableArgs:NO];
	[EXPFunctionElement registerFunction:table name:@"cosh"   opcode:COSHA  variableArgs:NO];
	[EXPFunctionElement registerFunction:table name:@"tanh"   opcode:TANHA  variableArgs:NO];
	[EXPFunctionElement registerFunction:table name:@"asinh"  opcode:ASINHA variableArgs:NO];
	[EXPFunctionElement registerFunction:table name:@"acosh"  opcode:ACOSHA variableArgs:NO];
	[EXPFunctionElement registerFunction:table name:@"atanh"  opcode:ATANHA variableArgs:NO];
	[EXPFunctionElement registerFunction:table name:@"erf"    opcode:ERFA   variableArgs:NO];

	[EXPFunctionElement registerFunction:table name:@"t"      opcode:TIME   variableArgs:NO];
	[EXPFunctionElement registerFunction:table name:@"tstart" opcode:TSTART variableArgs:NO];
	[EXPFunctionElement registerFunction:table name:@"tstop"  opcode:TSTOP  variableArgs:NO];

	[EXPFunctionElement registerFunction:table name:@"min"    opcode:MINN   variableArgs:YES];
	[EXPFunctionElement registerFunction:table name:@"max"    opcode:MAXN   variableArgs:YES];
	[EXPFunctionElement registerFunction:table name:@"mean"   opcode:MEANN  variableArgs:YES]; 
	[EXPFunctionElement registerFunction:table name:@"mod"    opcode:MOD    variableArgs:YES];
}

- (void) generateParseTree
{
}

- (NSString *)elementType
{
	return @"function";
}

- (void) setVariableArgs:(BOOL)variableArgs
{
	_variableArgs = variableArgs;
}

- (BOOL) variableArgs
{
	return _variableArgs;
}

- (BOOL) compile:(EXPStackMachine *)machine error:(NSError **)err withArguments:(NSArray *)arguments
{
	BOOL variableArgs = [self variableArgs];
	BOOL success = YES;
	int numArgs = [arguments count];
	
	if (variableArgs) {
		int i;
		for(i=0; (i<numArgs) && success; i++) {
			EXPExpression *argument = [arguments objectAtIndex:i];
			success = [argument compile:machine error:err];
			[machine putUInt:PSHA];
		}
	} else {
		if (numArgs>0) {
			EXPExpression *argument = [arguments objectAtIndex:0];
			success = [argument compile:machine error:err];
		}
	}
	
	if (success) {	
		unsigned int opcode = [self address];
		[machine putUInt:opcode];
		
		if (variableArgs) {
			[machine putUInt:(unsigned int)[arguments count]];
		}
	}
	
	return success;
}

@end
