rendered paste body// =====================================================================================================================================
// allen_cpu_base_arithmetic.c - Wed 13 jun 2007 00:09 CEST - Allen version 2.0
// =====================================================================================================================================
// Copyright (c) 2007, Archville, BSD License.
// A copy can be found here: http://www.opensource.org/licenses/bsd-license.php
// Initally based on Salvatore <antirez> Sanfilippo within Picol 0.1.0
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Garabatos de licor nor the names of its contributors may
// be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// This software is provided by the copyright holders and contributors
// "as is" and any express or implied warranties, including, but not
// limited to, the implied warranties of merchantability and fitness for
// a particular purpose are disclaimed. in no event shall the copyright owner or
// contributors be liable for any direct, indirect, incidental, special,
// exemplary, or consequential damages (including, but not limited to,
// procurement of substitute goods or services; loss of use, data, or
// profits; or business interruption) however caused and on any theory of
// liability, whether in contract, strict liability, or tort (including
// negligence or otherwise) arising in any way out of the use of this
// software, even if advised of the possibility of such damage.
// =====================================================================================================================================
// Include libraries.
// =====================================================================================================================================
#include <stdio.h> // Standard input/output.
#include <stdlib.h> // Standard C libraries.
#include <string.h> // String libraries.
#include <math.h> // Math libraries.
#include <ctype.h> // Types and conversion libraries.
#include "allen_interpreter.h" // Main interpreter library.
#include "allen_parser.h" // Main parser library.
// =====================================================================================================================================
// Parameters.
// =====================================================================================================================================
#define TBASE_ARITH_BSIZE 1024 // Buffer size.
// =====================================================================================================================================
// Possible errors.
// =====================================================================================================================================
#define TBASE_ARITH_EDIV "division: parameter is zero" // Error: Divide by zero returns inderminate result.
#define TBASE_ARITH_EMOD "modulus: parameter is zero" // Error: Modulus by zero returns indeterminate result.
// =====================================================================================================================================
// Tokens.
// =====================================================================================================================================
#define TBASE_ARITH_PLS "+" // Addition.
#define TBASE_ARITH_DPLS "++" // Increment.
#define TBASE_ARITH_MIN "-" // Substraction.
#define TBASE_ARITH_DMIN "--" // Decrement.
#define TBASE_ARITH_MUL "*" // Multiplication.
#define TBASE_ARITH_DMUL "**" // Square.
#define TBASE_ARITH_DIV "/" // Division.
#define TBASE_ARITH_DDIV "//" // Division without floating point.
#define TBASE_ARITH_MOD "%" // Modulus.
#define TBASE_ARITH_POW "^" // Pow.
// =====================================================================================================================================
// Basic arithmetic operators.
// =====================================================================================================================================
// Allows to perform regular arithmetic operations on value lists
// and return results based on their expresions.
// Index: Example: Result:
// AllenVM_CPU_BASE_ARITH_PLS(); :: + 2 3 - 4 1.000000
// AllenVM_CPU_BASE_ARITH_DPLS(); :: ++ 2 3.000000
// AllenVM_CPU_BASE_ARITH_MIN(); :: - 2 3 4 -5.000000
// AllenVM_CPU_BASE_ARITH_DMIN(); :: -- 2 1.000000
// AllenVM_CPU_BASE_ARITH_MUL(); :: * 2 3 4 24.000000
// AllenVM_CPU_BASE_ARITH_DMUL(); :: ** 2 4.000000
// AllenVM_CPU_BASE_ARITH_DIV(); :: / 2 3 4 0.166667
// AllenVM_CPU_BASE_ARITH_DDIV(); :: // 2 3 0
// AllenVM_CPU_BASE_ARITH_MOD(); :: % 10 3 1.000000
// AllenVM_CPU_BASE_ARITH_POW(); :: ^ 2 4 + 1 17.000000
// Total: 10.
// -------------------------------------------------------------------------------------------------------------------------------------
// Function: AllenVM_CPU_BASE_ARITH_PLS();
// Purpose: Addition.
// Returns: Expression result.
// -------------------------------------------------------------------------------------------------------------------------------------
static int AllenVM_CPU_BASE_ARITH_PLS(struct AllenInterp *i, int argc, char **argv, void *pd) {
char buf[TBASE_ARITH_BSIZE]; register int p,op; register float c=0; // Buffer and parameters.
if(argc>=2) c=atof(argv[1]); // Conversion.
for(op=1,p=2; p<argc; ++p) { // Loop through parameters.
if(atof(argv[p])==0) { // Check if we want to change.
if(!strcmp(TBASE_ARITH_PLS,argv[p])) { op = 1; continue; } // Change operator: Addition.
if(!strcmp(TBASE_ARITH_MIN,argv[p])) { op = 2; continue; } // Change operator: Substraction.
if(!strcmp(TBASE_ARITH_MUL,argv[p])) { op = 3; continue; } // Change operator: Multiplication.
if(!strcmp(TBASE_ARITH_DIV,argv[p])) { op = 4; continue; } // Change operator: Division.
if(!strcmp(TBASE_ARITH_MOD,argv[p])) { op = 5; continue; } // Change operator: Modulus.
if(!strcmp(TBASE_ARITH_POW,argv[p])) { op = 6; continue; } // Change operator: Pow.
}
switch(op) { // Look current operator.
case 1: c += atof(argv[p]); break; // Operate: Addition.
case 2: c -= atof(argv[p]); break; // Operate: Substraction.
case 3: c *= atof(argv[p]); break; // Operate: Multiplication.
case 4: c /= atof(argv[p]); break; // Operate: Division.
case 5: c = (int) c % atoi(argv[p]); break; // Operate: Modulus.
case 6: c = pow(c,atof(argv[p])); break; // Operate: Pow.
}}
snprintf(buf,TBASE_ARITH_BSIZE,"%f",c); // Copy result to buffer as float.
AllenVM_InterpSetResult(i,buf); // Set interpreter result.
return Allen_VM_OK; // Everything ok.
}
// -------------------------------------------------------------------------------------------------------------------------------------
// Function: AllenVM_CPU_BASE_ARITH_DPLS();
// Purpose: Increment.
// Returns: Expression result.
// -------------------------------------------------------------------------------------------------------------------------------------
static int AllenVM_CPU_BASE_ARITH_DPLS(struct AllenInterp *i, int argc, char **argv, void *pd) {
char buf[TBASE_ARITH_BSIZE]; register float c=0; // Buffer and parameters.
if(argc>=2) c=atof(argv[1])+1; // Increment.
snprintf(buf,TBASE_ARITH_BSIZE,"%f",c); // Copy result to buffer as float.
AllenVM_InterpSetResult(i,buf); // Set interpreter result.
return Allen_VM_OK; // Everything ok.
}
// -------------------------------------------------------------------------------------------------------------------------------------
// Function: AllenVM_CPU_BASE_ARITH_MIN();
// Purpose: Substraction.
// Returns: Expression result.
// -------------------------------------------------------------------------------------------------------------------------------------
static int AllenVM_CPU_BASE_ARITH_MIN(struct AllenInterp *i, int argc, char **argv, void *pd) {
char buf[TBASE_ARITH_BSIZE]; register int p,op; register float c=0; // Buffer and parameters.
if(argc>=2) c=atof(argv[1]); // Conversion.
for(op=2,p=2; p<argc; ++p) { // Loop through parameters.
if(atof(argv[p])==0) { // Check if we want to change.
if(!strcmp(TBASE_ARITH_PLS,argv[p])) { op = 1; continue; } // Change operator: Addition.
if(!strcmp(TBASE_ARITH_MIN,argv[p])) { op = 2; continue; } // Change operator: Substraction.
if(!strcmp(TBASE_ARITH_MUL,argv[p])) { op = 3; continue; } // Change operator: Multiplication.
if(!strcmp(TBASE_ARITH_DIV,argv[p])) { op = 4; continue; } // Change operator: Division.
if(!strcmp(TBASE_ARITH_MOD,argv[p])) { op = 5; continue; } // Change operator: Modulus.
if(!strcmp(TBASE_ARITH_POW,argv[p])) { op = 6; continue; } // Change operator: Pow.
}
switch(op) { // Look current operator.
case 1: c += atof(argv[p]); break; // Operate: Addition.
case 2: c -= atof(argv[p]); break; // Operate: Substraction.
case 3: c *= atof(argv[p]); break; // Operate: Multiplication.
case 4: c /= atof(argv[p]); break; // Operate: Division.
case 5: c = (int) c % atoi(argv[p]); break; // Operate: Modulus.
case 6: c = pow(c,atof(argv[p])); break; // Operate: Pow.
}}
snprintf(buf,TBASE_ARITH_BSIZE,"%f",c); // Copy result to buffer as float.
AllenVM_InterpSetResult(i,buf); // Set interpreter result.
return Allen_VM_OK; // Everything ok.
}
// -------------------------------------------------------------------------------------------------------------------------------------
// Function: AllenVM_CPU_BASE_ARITH_DMIN();
// Purpose: Decrement.
// Returns: Expression result.
// -------------------------------------------------------------------------------------------------------------------------------------
static int AllenVM_CPU_BASE_ARITH_DMIN(struct AllenInterp *i, int argc, char **argv, void *pd) {
char buf[TBASE_ARITH_BSIZE]; register float c=0; // Buffer and parameters.
if(argc>=2) c=atof(argv[1])-1; // Decrement.
snprintf(buf,TBASE_ARITH_BSIZE,"%f",c); // Copy result to buffer as float.
AllenVM_InterpSetResult(i,buf); // Set interpreter result.
return Allen_VM_OK; // Everything ok.
}
// -------------------------------------------------------------------------------------------------------------------------------------
// Function: AllenVM_CPU_BASE_ARITH_MUL();
// Purpose: Multiplication.
// Returns: Expression result.
// -------------------------------------------------------------------------------------------------------------------------------------
static int AllenVM_CPU_BASE_ARITH_MUL(struct AllenInterp *i, int argc, char **argv, void *pd) {
char buf[TBASE_ARITH_BSIZE]; register int p,op; register float c=0; // Buffer and parameters.
if(argc>=2) c=atof(argv[1]); // Conversion.
for(op=3,p=2; p<argc; ++p) { // Loop through parameters.
if(atof(argv[p])==0) { // Check if we want to change.
if(!strcmp(TBASE_ARITH_PLS,argv[p])) { op = 1; continue; } // Change operator: Addition.
if(!strcmp(TBASE_ARITH_MIN,argv[p])) { op = 2; continue; } // Change operator: Substraction.
if(!strcmp(TBASE_ARITH_MUL,argv[p])) { op = 3; continue; } // Change operator: Multiplication.
if(!strcmp(TBASE_ARITH_DIV,argv[p])) { op = 4; continue; } // Change operator: Division.
if(!strcmp(TBASE_ARITH_MOD,argv[p])) { op = 5; continue; } // Change operator: Modulus.
if(!strcmp(TBASE_ARITH_POW,argv[p])) { op = 6; continue; } // Change operator: Pow.
}
switch(op) { // Look current operator.
case 1: c += atof(argv[p]); break; // Operate: Addition.
case 2: c -= atof(argv[p]); break; // Operate: Substraction.
case 3: c *= atof(argv[p]); break; // Operate: Multiplication.
case 4: c /= atof(argv[p]); break; // Operate: Division.
case 5: c = (int) c % atoi(argv[p]); break; // Operate: Modulus.
case 6: c = pow(c,atof(argv[p])); break; // Operate: Pow.
}}
snprintf(buf,TBASE_ARITH_BSIZE,"%f",c); // Copy result to buffer as float.
AllenVM_InterpSetResult(i,buf); // Set interpreter result.
return Allen_VM_OK; // Everything ok.
}
// -------------------------------------------------------------------------------------------------------------------------------------
// Function: AllenVM_CPU_BASE_ARITH_DMUL();
// Purpose: Square.
// Returns: Expression result.
// -------------------------------------------------------------------------------------------------------------------------------------
static int AllenVM_CPU_BASE_ARITH_DMUL(struct AllenInterp *i, int argc, char **argv, void *pd) {
char buf[TBASE_ARITH_BSIZE]; register float c=0; // Buffer and parameters.
if(argc>=2) c=atof(argv[1])*atof(argv[1]); // Square.
snprintf(buf,TBASE_ARITH_BSIZE,"%f",c); // Copy result to buffer as float.
AllenVM_InterpSetResult(i,buf); // Set interpreter result.
return Allen_VM_OK; // Everything ok.
}
// -------------------------------------------------------------------------------------------------------------------------------------
// Function: AllenVM_CPU_BASE_ARITH_DIV();
// Purpose: Division.
// Returns: Expression result.
// -------------------------------------------------------------------------------------------------------------------------------------
static int AllenVM_CPU_BASE_ARITH_DIV(struct AllenInterp *i, int argc, char **argv, void *pd) {
char buf[TBASE_ARITH_BSIZE]; register int p,op; register float c=0; // Buffer and parameters.
if(argc>=2) c=atof(argv[1]); // Conversion.
for(op=4,p=2; p<argc; ++p) { // Loop through parameters.
if(atof(argv[p])==0) { // Check if we want to change.
if(!strcmp(TBASE_ARITH_PLS,argv[p])) { op = 1; continue; } // Change operator: Addition.
if(!strcmp(TBASE_ARITH_MIN,argv[p])) { op = 2; continue; } // Change operator: Substraction.
if(!strcmp(TBASE_ARITH_MUL,argv[p])) { op = 3; continue; } // Change operator: Multiplication.
if(!strcmp(TBASE_ARITH_DIV,argv[p])) { op = 4; continue; } // Change operator: Division.
if(!strcmp(TBASE_ARITH_MOD,argv[p])) { op = 5; continue; } // Change operator: Modulus.
if(!strcmp(TBASE_ARITH_POW,argv[p])) { op = 6; continue; } // Change operator: Pow.
}
switch(op) { // Look current operator.
case 1: c += atof(argv[p]); break; // Operate: Addition.
case 2: c -= atof(argv[p]); break; // Operate: Substraction.
case 3: c *= atof(argv[p]); break; // Operate: Multiplication.
case 4: c /= atof(argv[p]); break; // Operate: Division.
case 5: c = (int) c % atoi(argv[p]); break; // Operate: Modulus.
case 6: c = pow(c,atof(argv[p])); break; // Operate: Pow.
}}
snprintf(buf,TBASE_ARITH_BSIZE,"%f",c); // Copy result to buffer as float.
AllenVM_InterpSetResult(i,buf); // Set interpreter result.
return Allen_VM_OK; // Everything ok.
}
// -------------------------------------------------------------------------------------------------------------------------------------
// Function: AllenVM_CPU_BASE_ARITH_DDIV();
// Purpose: Division without floating point.
// Returns: Expression result.
// -------------------------------------------------------------------------------------------------------------------------------------
static int AllenVM_CPU_BASE_ARITH_DDIV(struct AllenInterp *i, int argc, char **argv, void *pd) {
char buf[TBASE_ARITH_BSIZE]; register int p; register float c=0; // Buffer and parameters.
if(argc>=2) c=atof(argv[1]); // Conversion.
for(p=2; p<argc; ++p) {
if(atof(argv[p]) == 0) return AllenVM_CPU_Error(i,TBASE_ARITH_EDIV); // Look for errors.
c /= atof(argv[p]); // Division.
}
snprintf(buf,TBASE_ARITH_BSIZE,"%d",(int) c); // Copy result to buffer as integer.
AllenVM_InterpSetResult(i,buf); // Set interpreter result.
return Allen_VM_OK; // Everything ok.
}
// -------------------------------------------------------------------------------------------------------------------------------------
// Function: AllenVM_CPU_BASE_ARITH_MOD();
// Purpose: Modulus.
// Returns: Expression result.
// -------------------------------------------------------------------------------------------------------------------------------------
static int AllenVM_CPU_BASE_ARITH_MOD(struct AllenInterp *i, int argc, char **argv, void *pd) {
char buf[TBASE_ARITH_BSIZE]; register int p,op; register float c=0; // Buffer and parameters.
if(argc>=2) c=atof(argv[1]); // Conversion.
for(op=5,p=2; p<argc; ++p) { // Loop through parameters.
if(atof(argv[p])==0) { // Check if we want to change.
if(!strcmp(TBASE_ARITH_PLS,argv[p])) { op = 1; continue; } // Change operator: Addition.
if(!strcmp(TBASE_ARITH_MIN,argv[p])) { op = 2; continue; } // Change operator: Substraction.
if(!strcmp(TBASE_ARITH_MUL,argv[p])) { op = 3; continue; } // Change operator: Multiplication.
if(!strcmp(TBASE_ARITH_DIV,argv[p])) { op = 4; continue; } // Change operator: Division.
if(!strcmp(TBASE_ARITH_MOD,argv[p])) { op = 5; continue; } // Change operator: Modulus.
if(!strcmp(TBASE_ARITH_POW,argv[p])) { op = 6; continue; } // Change operator: Pow.
}
switch(op) { // Look current operator.
case 1: c += atof(argv[p]); break; // Operate: Addition.
case 2: c -= atof(argv[p]); break; // Operate: Substraction.
case 3: c *= atof(argv[p]); break; // Operate: Multiplication.
case 4: c /= atof(argv[p]); break; // Operate: Division.
case 5: c = (int) c % atoi(argv[p]); break; // Operate: Modulus.
case 6: c = pow(c,atof(argv[p])); break; // Operate: Pow.
}}
snprintf(buf,TBASE_ARITH_BSIZE,"%f",c); // Copy result to buffer as float.
AllenVM_InterpSetResult(i,buf); // Set interpreter result.
return Allen_VM_OK; // Everything ok.
}
// -------------------------------------------------------------------------------------------------------------------------------------
// Function: AllenVM_CPU_BASE_ARITH_POW();
// Purpose: Pow.
// Returns: Expression result.
// -------------------------------------------------------------------------------------------------------------------------------------
static int AllenVM_CPU_BASE_ARITH_POW(struct AllenInterp *i, int argc, char **argv, void *pd) {
char buf[TBASE_ARITH_BSIZE]; register int p,op; register float c=0; // Buffer and parameters.
if(argc>=2) c=atof(argv[1]); // Conversion.
for(op=6,p=2; p<argc; ++p) { // Loop through parameters.
if(atof(argv[p])==0) { // Check if we want to change.
if(!strcmp(TBASE_ARITH_PLS,argv[p])) { op = 1; continue; } // Change operator: Addition.
if(!strcmp(TBASE_ARITH_MIN,argv[p])) { op = 2; continue; } // Change operator: Substraction.
if(!strcmp(TBASE_ARITH_MUL,argv[p])) { op = 3; continue; } // Change operator: Multiplication.
if(!strcmp(TBASE_ARITH_DIV,argv[p])) { op = 4; continue; } // Change operator: Division.
if(!strcmp(TBASE_ARITH_MOD,argv[p])) { op = 5; continue; } // Change operator: Modulus.
if(!strcmp(TBASE_ARITH_POW,argv[p])) { op = 6; continue; } // Change operator: Pow.
}
switch(op) { // Look current operator.
case 1: c += atof(argv[p]); break; // Operate: Addition.
case 2: c -= atof(argv[p]); break; // Operate: Substraction.
case 3: c *= atof(argv[p]); break; // Operate: Multiplication.
case 4: c /= atof(argv[p]); break; // Operate: Division.
case 5: c = (int) c % atoi(argv[p]); break; // Operate: Modulus.
case 6: c = pow(c,atof(argv[p])); break; // Operate: Pow.
}}
snprintf(buf,TBASE_ARITH_BSIZE,"%f",c); // Copy result to buffer as float.
AllenVM_InterpSetResult(i,buf); // Set interpreter result.
return Allen_VM_OK; // Everything ok.
}
// -------------------------------------------------------------------------------------------------------------------------------------
// Function: AllenVM_CPU_BASE_ARITH_ADD();
// Purpose: Add instructions to the CPU.
// -------------------------------------------------------------------------------------------------------------------------------------
// Description: Register VM instructions for the interpreter.
// -------------------------------------------------------------------------------------------------------------------------------------
void AllenVM_CPU_BASE_ARITH_ADD(struct AllenInterp *i) {
AllenVM_InterpSetCommand(i,TBASE_ARITH_PLS, AllenVM_CPU_BASE_ARITH_PLS, NULL); // Addition.
AllenVM_InterpSetCommand(i,TBASE_ARITH_DPLS, AllenVM_CPU_BASE_ARITH_DPLS, NULL); // Increment.
AllenVM_InterpSetCommand(i,TBASE_ARITH_MIN, AllenVM_CPU_BASE_ARITH_MIN, NULL); // Substraction.
AllenVM_InterpSetCommand(i,TBASE_ARITH_DMIN, AllenVM_CPU_BASE_ARITH_DMIN, NULL); // Decrement.
AllenVM_InterpSetCommand(i,TBASE_ARITH_MUL, AllenVM_CPU_BASE_ARITH_MUL, NULL); // Multiplication.
AllenVM_InterpSetCommand(i,TBASE_ARITH_DMUL, AllenVM_CPU_BASE_ARITH_DMUL, NULL); // Square.
AllenVM_InterpSetCommand(i,TBASE_ARITH_DIV, AllenVM_CPU_BASE_ARITH_DIV, NULL); // Division.
AllenVM_InterpSetCommand(i,TBASE_ARITH_DDIV, AllenVM_CPU_BASE_ARITH_DDIV, NULL); // Division without floating point.
AllenVM_InterpSetCommand(i,TBASE_ARITH_MOD, AllenVM_CPU_BASE_ARITH_MOD, NULL); // Modulus.
AllenVM_InterpSetCommand(i,TBASE_ARITH_POW, AllenVM_CPU_BASE_ARITH_POW, NULL); // Pow.
}
// =====================================================================================================================================
// EOF
// =====================================================================================================================================
// Compiler parameters: Gcc -O2 -lm
// Recommended editor: Scite/Gedit/Vim.