//
//  EXPBinOp.m
//  Expression
//
//  Created by Ashley on 28/02/2006.
//  Copyright 2006 __MyCompanyName__. All rights reserved.
//

#include <math.h>
#import "EXPExpression.h"
#import "EXPUnaryOp.h"
#import "EXPBinOp.h"
#import "EXPSymbolTable.h"
#import "EXPConstant.h"
//#import "EXPParameter.h"
#import "EXPAssemblerConstants.h"

@implementation EXPBinOp

- (id)initWithLeft:(id)left AndRight:(id) right
{
	[super initWithLeft:left];
	[self setRight:right];
	return self;
}

- (id) init
{
	return [self initWithLeft:nil  AndRight:nil];
	
}

- (id) right
{
	return _right;
}

- (void)setRight:(id)right
{
	[right retain];
	[_right release];
	_right = right;
}

- (BOOL) compile:(EXPStackMachine *)machine error:(NSError **)err
{
	return NO;
}

- (BOOL) compile:(EXPStackMachine *)machine error:(NSError **)err opcode:(unsigned int)opcode
{
	EXPExpression *left = [self left];
	EXPExpression *right = [self right];
	
	if ([right isSimple]) {
		[left compile:machine error:err];
		[right compile:machine error:err opcode:opcode];
	} else {
		[right compile:machine error:err/* opcode:LDAP*/];
		[machine putUInt:PSHA];
		[left compile:machine error:err/* opcode:LDAP*/];
		[machine putUInt:(opcode + SMODE)];
	}
	
	return YES;
}

- (double) result
{
	return 0.0;
}

- (void) dump
{
	[super dump];
	[[self right] dump];
}

- (void) dealloc
{
//	printf("EXPBinOp - (void) dealloc %s\n", [[[self class] description] UTF8String]);
	[_right release];

	[super dealloc];
}

@end

@implementation EXPAddOp

- (NSString *)description
{
	return [NSString stringWithFormat:@"(%@) + (%@)", [[self left] description], [[self right] description]];
}

- (double) result
{
	double a = [[self left] result];
	double b = [[self right] result]; 
	return a + b;
}

- (BOOL) compile:(EXPStackMachine *)machine error:(NSError **)err
{
	BOOL success = [super compile:machine error:err opcode:ADDP];
	return success;
}

@end

@implementation EXPSubOp

- (NSString *)description
{
	return [NSString stringWithFormat:@"(%@) - (%@)", [[self left] description], [[self right] description]];
}

- (double) result
{
	return [[self left] result] - [[self right] result];
}

- (BOOL) compile:(EXPStackMachine *)machine error:(NSError **)err
{
	BOOL success = [super compile:machine error:err opcode:SUBP];
	return success;
}

@end

@implementation EXPMultOp

- (NSString *)description
{
	return [NSString stringWithFormat:@"(%@) * (%@)", [[self left] description], [[self right] description]];
}

- (double) result
{
	return [[self left] result] * [[self right] result];
}

- (BOOL) compile:(EXPStackMachine *)machine error:(NSError **)err
{
	BOOL success = [super compile:machine error:err opcode:MULP];
	return success;
}

@end

@implementation EXPDivOp

- (NSString *)description
{
	return [NSString stringWithFormat:@"(%@) / (%@)", [[self left] description], [[self right] description]];
}

- (double) result
{
	double y = [[self right] result];
	if (y!=0.0) {
		return [[self left] result] / y;
	} else {
		return 0.0;
	}
}

- (BOOL) compile:(EXPStackMachine *)machine error:(NSError **)err
{
	BOOL success = [super compile:machine error:err opcode:DVDP];
	return success;
}

@end

@implementation EXPPwrOp

- (NSString *)description
{
	return [NSString stringWithFormat:@"(%@) ^ (%@)", [[self left] description], [[self right] description]];
}

- (double) result
{
	double y = [[self right] result];
	return pow([[self left] result], y);
}

- (BOOL) compile:(EXPStackMachine *)machine error:(NSError **)err
{
	BOOL success = [super compile:machine error:err opcode:PWRP];
	return success;
}

@end

@implementation EXPAndOp

- (NSString *)description
{
	return [NSString stringWithFormat:@"(%@) and (%@)", [[self left] description], [[self right] description]];
}

- (double) result
{
	double y = [[self right] result];
	if ((int)y!=0) {
		return [[self left] result];
	} else {
		return 0.0;
	}
}

- (BOOL) compile:(EXPStackMachine *)machine error:(NSError **)err
{
	BOOL success = [[self left] compile:machine error:err];
	if (!success) {
		return NO;
	}
	
	[machine putUInt:BEQ];
	unsigned int branchpc = [machine pc];
	[machine putUInt:0];
	
	success = [[self right] compile:machine error:err];
	if (!success) {
		return NO;
	}
	
	[machine putUInt:[machine pc] at:branchpc];
	
	return success;
}

@end

@implementation EXPOrOp

- (NSString *)description
{
	return [NSString stringWithFormat:@"(%@) or (%@)", [[self left] description], [[self right] description]];
}

- (double) result
{
	double y = [[self right] result];
	if ((int)y==0) {
		return [[self left] result];
	} else {
		return 0.0;
	}
}

- (BOOL) compile:(EXPStackMachine *)machine error:(NSError **)err
{
	BOOL success = [[self left] compile:machine error:err];
	if (!success) {
		return NO;
	}
	
	[machine putUInt:BNE];
	unsigned int branchpc = [machine pc];
	[machine putUInt:0];
	
	success = [[self right] compile:machine error:err];
	if (!success) {
		return NO;
	}
	
	[machine putUInt:[machine pc] at:branchpc];
	
	return success;
}

@end

@implementation EXPEqualToOp  

- (NSString *)description
{
	return [NSString stringWithFormat:@"(%@) == (%@)", [[self left] description], [[self right] description]];
}

- (double) result
{
	return (double)([[self left] result] == [[self right] result]);
}

- (BOOL) compile:(EXPStackMachine *)machine error:(NSError **)err
{
	BOOL success = [super compile:machine error:err opcode:EQUP];
	return success;
}

@end 

@implementation EXPNotEqualToOp 

- (NSString *)description
{
	return [NSString stringWithFormat:@"(%@) != (%@)", [[self left] description], [[self right] description]];
}

- (double) result
{
	return (double)([[self left] result] != [[self right] result]);
}

- (BOOL) compile:(EXPStackMachine *)machine error:(NSError **)err
{
	BOOL success = [super compile:machine error:err opcode:NEQP];
	return success;
}

@end 

@implementation EXPGreaterThanOp 

- (NSString *)description
{
	return [NSString stringWithFormat:@"(%@) > (%@)", [[self left] description], [[self right] description]];
}

- (double) result
{
	return (double)([[self left] result] > [[self right] result]);
}

- (BOOL) compile:(EXPStackMachine *)machine error:(NSError **)err
{
	BOOL success = [super compile:machine error:err opcode:GTHP];
	return success;
}

@end 

@implementation EXPLessThanOp 

- (NSString *)description
{
	return [NSString stringWithFormat:@"(%@) < (%@)", [[self left] description], [[self right] description]];
}

- (double) result
{
	return (double)([[self left] result] < [[self right] result]);
}

- (BOOL) compile:(EXPStackMachine *)machine error:(NSError **)err
{
	BOOL success = [super compile:machine error:err opcode:LTHP];
	return success;
}

@end 

@implementation EXPGreaterThanOrEqualToOp 

- (NSString *)description
{
	return [NSString stringWithFormat:@"(%@) >= (%@)", [[self left] description], [[self right] description]];
}

- (double) result
{
	return (double)([[self left] result] >= [[self right] result]);
}

- (BOOL) compile:(EXPStackMachine *)machine error:(NSError **)err
{
	BOOL success = [super compile:machine error:err opcode:GTEP];
	return success;
}

@end 

@implementation EXPLessThanOrEqualToOp 

- (NSString *)description
{
	return [NSString stringWithFormat:@"(%@) <= (%@)", [[self left] description], [[self right] description]];
}

- (double) result
{
	return (double)([[self left] result] <= [[self right] result]);
}

- (BOOL) compile:(EXPStackMachine *)machine error:(NSError **)err
{
	BOOL success = [super compile:machine error:err opcode:LTEP];
	return success;
}

@end 
