I thought the topic needed a change of title.
At the moment I'm making a Python to C converter. I've replicated the functionality of Python operators in C as well as variables (Limited to integers, floating-point numbers,booleans, the None value and strings at the moment). Next I need to create a Python expression to C expression converter which will use my C implementations of Python operators.
Code: Select all
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdint.h>
#include <math.h>
typedef enum {
INT = 0,
FLOAT = 1,
STRING = 2,
NONE = 3,
BOOL = 4
} TYPE;
typedef struct {
TYPE type;
void * data;
} Variable;
typedef Variable ** var; //Convenience typedef for pointer to variable pointer
typedef struct {
size_t size;
Variable *** pool; //Pointer to the array of pointers to the Variable structure pointers. Pointer required for memory allocation and array consists of pointers to pointers so the pointers to the Variable structures can be changed throughtout different functions.
} VarPool; //Variable pools will just be used to deallocate all variables at the end of a scope
VarPool * global_pool; //Pool for global scope
VarPool ** temp_pool_stack; //Keeps track of pools for temporary variables in expressions
unsigned int pool_stack_size;
VarPool ** pool_stack; //Keeps track of pools in stack
unsigned int pool_stack_size;
char ** string_pool; //Hold strings needing deletion
unsigned int string_pool_size;
void init_pool_stack(){
pool_stack = malloc(sizeof(VarPool *)); //Start with global_pool
pool_stack_size = 1;
global_pool = malloc(sizeof(VarPool));
pool_stack[0] = global_pool;
global_pool->pool = NULL;
global_pool->size = 0;
//Temp pool stack
temp_pool_stack = malloc(sizeof(VarPool *));
temp_pool_stack[0] = malloc(sizeof(VarPool));
temp_pool_stack[0]->pool = NULL;
temp_pool_stack[0]->size = 0;
//Assign NULL pointer to string pool
string_pool = NULL;
string_pool_size = 0;
}
void make_pool(){
VarPool * var_pool = malloc(sizeof(VarPool));
pool_stack_size++;
pool_stack = realloc(pool_stack, pool_stack_size*sizeof(VarPool *));
pool_stack[pool_stack_size-1] = var_pool;
var_pool->pool = NULL;
var_pool->size = 0;
//Temporary variable pool
var_pool = malloc(sizeof(VarPool));
temp_pool_stack = realloc(temp_pool_stack, pool_stack_size*sizeof(VarPool *));
temp_pool_stack[pool_stack_size-1] = var_pool;
var_pool->pool = NULL;
var_pool->size = 0;
}
Variable ** new_var(){ //Makes new variable
Variable ** return_variable = malloc(sizeof(Variable *));
Variable * new_variable = malloc(sizeof(Variable));
new_variable->data = NULL;
VarPool * var_pool = pool_stack[pool_stack_size-1]; //Current variable pool on top of stack
var_pool->size++;
var_pool->pool = realloc(var_pool->pool,var_pool->size*sizeof(Variable **));
*return_variable = new_variable;
var_pool->pool[var_pool->size - 1] = return_variable;
return return_variable; //Return pointer to new pointer so pointer can be changed to NULL when deleted
}
Variable ** assign_int(Variable ** variable,int64_t integer){
Variable * var_ptr = *variable;
free(var_ptr->data); //Free previous data
int64_t * data = malloc(sizeof(int64_t));
*data = integer;
var_ptr->data = data;
var_ptr->type = INT;
return variable;
}
Variable ** assign_float(Variable ** variable,double number){
Variable * var_ptr = *variable;
free(var_ptr->data); //Free previous data
double * data = malloc(sizeof(double));
*data = number;
var_ptr->data = data;
var_ptr->type = FLOAT;
return variable;
}
Variable ** assign_string(Variable ** variable,char * string){
Variable * var_ptr = *variable;
free(var_ptr->data); //Free previous data
var_ptr->data = malloc(strlen(string)*sizeof(char));
strcpy(var_ptr->data,string);
var_ptr->type = STRING;
return variable;
}
Variable ** assign_none(Variable ** variable){
Variable * var_ptr = *variable;
free(var_ptr->data); //Free previous data
var_ptr->data = NULL;
var_ptr->type = NONE;
return variable;
}
Variable ** assign_bool(Variable ** variable,bool boolean){
Variable * var_ptr = *variable;
free(var_ptr->data); //Free previous data
bool * data = malloc(sizeof(bool));
*data = boolean;
var_ptr->data = data;
var_ptr->type = BOOL;
return variable;
}
Variable ** new_temp_var(){
Variable ** return_variable = malloc(sizeof(Variable *));
Variable * new_variable = malloc(sizeof(Variable));
new_variable->data = NULL;
VarPool * var_pool = temp_pool_stack[pool_stack_size-1]; //Current temporary variable pool on top of stack
var_pool->size++;
var_pool->pool = realloc(var_pool->pool,var_pool->size*sizeof(Variable **));
*return_variable = new_variable;
var_pool->pool[var_pool->size - 1] = return_variable;
return return_variable; //Return pointer to new pointer so pointer can be changed to NULL when deleted
}
Variable ** temp_int(int64_t integer){
Variable ** new_variable = new_temp_var();
Variable * var_ptr = *new_variable;
int64_t * data = malloc(sizeof(int64_t));
*data = integer;
var_ptr->data = data;
var_ptr->type = INT;
return new_variable;
}
Variable ** temp_float(double number){
Variable ** new_variable = new_temp_var();
Variable * var_ptr = *new_variable;
double * data = malloc(sizeof(double));
*data = number;
var_ptr->data = data;
var_ptr->type = FLOAT;
return new_variable;
}
Variable ** temp_string(char * string){
Variable ** new_variable = new_temp_var();
Variable * var_ptr = *new_variable;
var_ptr->data = malloc(strlen(string)*sizeof(char));
strcpy(var_ptr->data,string);
var_ptr->type = STRING;
return new_variable;
}
Variable ** temp_none(){
Variable ** new_variable = new_temp_var();
Variable * var_ptr = *new_variable;
var_ptr->data = NULL;
var_ptr->type = NONE;
return new_variable;
}
Variable ** temp_bool(bool boolean){
Variable ** new_variable = new_temp_var();
Variable * var_ptr = *new_variable;
bool * data = malloc(sizeof(bool));
*data = boolean;
var_ptr->data = data;
var_ptr->type = BOOL;
return new_variable;
}
void empty_temporary_pool(){
VarPool * var_pool = temp_pool_stack[pool_stack_size-1]; //Current variable pool on top of stack
for (int x = 0; x < var_pool->size; x++) {
if(*var_pool->pool[x] != NULL){
free((*var_pool->pool[x])->data);//Free variable data
free(*var_pool->pool[x]); //Free variable
}
free(var_pool->pool[x]); //Free variable pointer
}
var_pool->size = 0;
}
//Return c values from variables. Empty temporary pool when done to clear expression data
bool bool_val(Variable ** var_ptr){
Variable * variable = *var_ptr;
bool ans;
switch (variable->type) {
case INT:
ans = *(int64_t *)(variable->data) != 0;
break;
case FLOAT:
ans = *(double *)(variable->data) != 0;
break;
case STRING:
ans = strlen(variable->data) != 0;
break;
case NONE:
ans = false;
break;
case BOOL:
ans = *(bool *)(variable->data);
break;
}
empty_temporary_pool();
return ans;
}
Variable ** to_int(Variable ** var_ptr){
Variable * variable = *var_ptr;
switch (variable->type) {
case INT:
return var_ptr;
break;
case FLOAT:
return temp_int((int64_t)*(double *)(variable->data) != 0);
break;
case STRING:
return temp_int(strtol(variable->data,NULL,10));
break;
case BOOL:
return temp_int((int64_t)*(bool *)(variable->data));
break;
}
return temp_int(0);
}
int64_t int_val(Variable ** var_ptr){
Variable * variable = *var_ptr;
int64_t ans;
switch (variable->type) {
case INT:
ans = *(int64_t *)(variable->data);
break;
case FLOAT:
ans = (int64_t)*(double *)(variable->data);
break;
case STRING:
ans = strtol(variable->data,NULL,10);
break;
case NONE:
ans = false;
break;
case BOOL:
ans = (int64_t)*(bool *)(variable->data);
break;
}
empty_temporary_pool();
return ans;
}
char * string_val(Variable ** var_ptr){
Variable * variable = *var_ptr;
char * ans;
long long int integer;
double number;
switch (variable->type) {
case INT:
integer = *(int64_t *)(variable->data);
ans = malloc(sizeof(char) * (int)(log10(integer)) + 1);
sprintf(ans,"%lli",integer );
break;
case FLOAT:
number = *(double *)(variable->data);
ans = malloc(sizeof(char) * (int)(log10(number)) + 1);
sprintf(ans,"%f",number);
break;
case STRING:
ans = malloc(sizeof(char) * strlen(variable->data));
strcpy(ans,variable->data);
break;
case NONE:
ans = malloc(sizeof(char) * 5);
ans = "None";
break;
case BOOL:
if (*(bool *)(variable->data)) {
ans = malloc(sizeof(char) * 5);
ans = "True";
}else {
ans = malloc(sizeof(char) * 6);
ans = "False";
}
break;
}
empty_temporary_pool();
//Add string to string pool
string_pool_size++;
string_pool = realloc(string_pool, sizeof(char *)*string_pool_size);
string_pool[string_pool_size - 1] = ans;
return ans;
}
//Arithmetic
Variable ** add(Variable ** var1_ptr, Variable ** var2_ptr){
Variable * var1 = *var1_ptr;
Variable * var2 = *var2_ptr;
switch (var1->type) {
case INT:
switch (var2->type) {
case INT:
return temp_int(*(int64_t *)(var1->data) * *(int64_t *)(var2->data));
break;
case FLOAT:
return temp_float(*(int64_t *)(var1->data) * *(double *)(var2->data));
break;
case BOOL:
return temp_int(*(int64_t *)(var1->data) * *(bool *)(var2->data));
break;
}
break;
case STRING:
if (var2->type == STRING) {
char * new_string = malloc(sizeof(char) * (strlen(var1->data) + strlen(var2->data)));
strcpy(new_string,var1->data);
strcat(new_string,var2->data);
Variable ** return_val = temp_string(new_string);
free(new_string);
return return_val;
}
break;
case FLOAT:
switch (var2->type) {
case INT:
return temp_float(*(double *)(var1->data) * *(int64_t *)(var2->data));
break;
case FLOAT:
return temp_float(*(double *)(var1->data) * *(double *)(var2->data));
break;
case BOOL:
return temp_float(*(double *)(var1->data) * *(bool *)(var2->data));
break;
}
break;
case BOOL:
switch (var2->type) {
case INT:
return temp_int(*(bool *)(var1->data) * *(int64_t *)(var2->data));
break;
case FLOAT:
return temp_float(*(bool *)(var1->data) * *(double *)(var2->data));
break;
case BOOL:
return temp_int(*(bool *)(var1->data) * *(bool *)(var2->data));
break;
}
break;
}
return temp_bool(false);
}
Variable ** subtract(Variable ** var1_ptr, Variable ** var2_ptr){
Variable * var1 = *var1_ptr;
Variable * var2 = *var2_ptr;
switch (var1->type) {
case INT:
switch (var2->type) {
case INT:
return temp_int(*(int64_t *)(var1->data) - *(int64_t *)(var2->data));
break;
case FLOAT:
return temp_float(*(int64_t *)(var1->data) - *(double *)(var2->data));
break;
case BOOL:
return temp_int(*(int64_t *)(var1->data) - *(bool *)(var2->data));
break;
}
break;
case FLOAT:
switch (var2->type) {
case INT:
return temp_float(*(double *)(var1->data) - *(int64_t *)(var2->data));
break;
case FLOAT:
return temp_float(*(double *)(var1->data) - *(double *)(var2->data));
break;
case BOOL:
return temp_float(*(double *)(var1->data) - *(bool *)(var2->data));
break;
}
break;
case BOOL:
switch (var2->type) {
case INT:
return temp_int(*(bool *)(var1->data) - *(int64_t *)(var2->data));
break;
case FLOAT:
return temp_float(*(bool *)(var1->data) - *(double *)(var2->data));
break;
case BOOL:
return temp_int(*(bool *)(var1->data) - *(bool *)(var2->data));
break;
}
break;
}
return temp_bool(false);
}
Variable ** multiply(Variable ** var1_ptr, Variable ** var2_ptr){
Variable * var1 = *var1_ptr;
Variable * var2 = *var2_ptr;
long long int integer;
switch (var1->type) {
case INT:
switch (var2->type) {
case INT:
return temp_int(*(int64_t *)(var1->data) * *(int64_t *)(var2->data));
break;
case FLOAT:
return temp_float(*(int64_t *)(var1->data) * *(double *)(var2->data));
break;
case STRING:
integer = (long long int)*(int64_t *)(var1->data);
if (integer) {
char * new_string = malloc(sizeof(char) * strlen(var2->data) * integer);
strcpy(new_string,var2->data);
for (int x = 1; x < integer; x++) {
strcat(new_string,var2->data);
}
Variable ** return_val = temp_string(new_string);
free(new_string);
return return_val;
}else{
return temp_string("");
}
break;
case BOOL:
return temp_int(*(int64_t *)(var1->data) * *(bool *)(var2->data));
break;
}
break;
case STRING:
if (var2->type == INT) {
integer = (long long int)*(int64_t *)(var2->data);
if (integer) {
char * new_string = malloc(sizeof(char) * strlen(var1->data) * integer);
strcpy(new_string,var1->data);
for (int x = 1; x < integer; x++) {
strcat(new_string,var1->data);
}
Variable ** return_val = temp_string(new_string);
free(new_string);
return return_val;
}else{
return temp_string("");
}
}else if (var2->type == BOOL) {
if (*(bool *)(var2->data)) {
return var1_ptr;
}else{
return temp_string("");
}
}
break;
case FLOAT:
switch (var2->type) {
case INT:
return temp_float(*(double *)(var1->data) * *(int64_t *)(var2->data));
break;
case FLOAT:
return temp_float(*(double *)(var1->data) * *(double *)(var2->data));
break;
case BOOL:
return temp_float(*(double *)(var1->data) * *(bool *)(var2->data));
break;
}
break;
case BOOL:
switch (var2->type) {
case INT:
return temp_int(*(bool *)(var1->data) * *(int64_t *)(var2->data));
break;
case FLOAT:
return temp_float(*(bool *)(var1->data) * *(double *)(var2->data));
break;
case STRING:
if (*(bool *)(var1->data)) {
return var2_ptr;
}else{
return temp_string("");
}
break;
case BOOL:
return temp_int(*(bool *)(var1->data) * *(bool *)(var2->data));
break;
}
break;
}
return temp_bool(false);
}
Variable ** divide(Variable ** var1_ptr, Variable ** var2_ptr){
Variable * var1 = *var1_ptr;
Variable * var2 = *var2_ptr;
switch (var1->type) {
case INT:
switch (var2->type) {
case INT:
return temp_int(*(int64_t *)(var1->data) / *(int64_t *)(var2->data));
break;
case FLOAT:
return temp_float(*(int64_t *)(var1->data) / *(double *)(var2->data));
break;
case BOOL:
return temp_int(*(int64_t *)(var1->data) / *(bool *)(var2->data));
break;
}
break;
case FLOAT:
switch (var2->type) {
case INT:
return temp_float(*(double *)(var1->data) / *(int64_t *)(var2->data));
break;
case FLOAT:
return temp_float(*(double *)(var1->data) / *(double *)(var2->data));
break;
case BOOL:
return temp_float(*(double *)(var1->data) / *(bool *)(var2->data));
break;
}
break;
case BOOL:
switch (var2->type) {
case INT:
return temp_int(*(bool *)(var1->data) / *(int64_t *)(var2->data));
break;
case FLOAT:
return temp_float(*(bool *)(var1->data) / *(double *)(var2->data));
break;
case BOOL:
return temp_int(*(bool *)(var1->data) / *(bool *)(var2->data));
break;
}
break;
}
return temp_bool(false);
}
Variable ** exponentiate(Variable ** var1_ptr, Variable ** var2_ptr){
Variable * var1 = *var1_ptr;
Variable * var2 = *var2_ptr;
switch (var1->type) {
case INT:
switch (var2->type) {
case INT:
return temp_int(pow(*(int64_t *)(var1->data), *(int64_t *)(var2->data)));
break;
case FLOAT:
return temp_float(pow(*(int64_t *)(var1->data), *(double *)(var2->data)));
break;
case BOOL:
return temp_int(pow(*(int64_t *)(var1->data), *(bool *)(var2->data)));
break;
}
break;
case FLOAT:
switch (var2->type) {
case INT:
return temp_float(pow(*(double *)(var1->data), *(int64_t *)(var2->data)));
break;
case FLOAT:
return temp_float(pow(*(double *)(var1->data), *(double *)(var2->data)));
break;
case BOOL:
return temp_float(pow(*(double *)(var1->data), *(bool *)(var2->data)));
break;
}
break;
case BOOL:
switch (var2->type) {
case INT:
return temp_int(pow(*(bool *)(var1->data), *(int64_t *)(var2->data)));
break;
case FLOAT:
return temp_float(pow(*(bool *)(var1->data), *(double *)(var2->data)));
break;
case BOOL:
return temp_int(pow(*(bool *)(var1->data), *(bool *)(var2->data)));
break;
}
break;
}
return temp_bool(false);
}
Variable ** modulo(Variable ** var1_ptr, Variable ** var2_ptr){
Variable * var1 = *var1_ptr;
Variable * var2 = *var2_ptr;
switch (var1->type) {
case INT:
switch (var2->type) {
case INT:
return temp_int(*(int64_t *)(var1->data) % *(int64_t *)(var2->data));
break;
case BOOL:
return temp_int(*(int64_t *)(var1->data) % *(bool *)(var2->data));
break;
}
break;
case BOOL:
switch (var2->type) {
case INT:
return temp_int(*(bool *)(var1->data) % *(int64_t *)(var2->data));
break;
case BOOL:
return temp_int(*(bool *)(var1->data) % *(bool *)(var2->data));
break;
}
break;
}
return temp_bool(false);
}
Variable ** negative(Variable ** var_ptr){
Variable * variable = *var_ptr;
switch (variable->type) {
case INT:
return temp_int(-*(int64_t *)(variable->data));
break;
case FLOAT:
return temp_float(-*(double *)(variable->data));
break;
case BOOL:
return temp_int(-*(bool *)(variable->data));
break;
}
return temp_bool(false);
}
//Boolean algebra
Variable ** and(Variable ** var1_ptr, Variable ** var2_ptr){
Variable * var1 = *var1_ptr;
switch (var1->type) {
case INT:
if(*(int64_t *)(var1->data)){
return var2_ptr;
}else{
return var1_ptr;
}
break;
case FLOAT:
if (*(double *)(var1->data)) {
return var2_ptr;
}else{
return var1_ptr;
}
break;
case STRING:
if (strlen(var1->data)) {
return var2_ptr;
}else{
return var1_ptr;
}
break;
case NONE:
return var1_ptr;
break;
case BOOL:
if(*(bool *)(var1->data)){
return var2_ptr;
}else{
return var1_ptr;
}
break;
}
return temp_bool(false);
}
Variable ** or(Variable ** var1_ptr, Variable ** var2_ptr){
Variable * var1 = *var1_ptr;
switch (var1->type) {
case INT:
if(*(int64_t *)(var1->data)){
return var1_ptr;
}else{
return var2_ptr;
}
break;
case FLOAT:
if (*(double *)(var1->data)) {
return var1_ptr;
}else{
return var2_ptr;
}
break;
case STRING:
if (strlen(var1->data)) {
return var1_ptr;
}else{
return var2_ptr;
}
break;
case NONE:
return var2_ptr;
break;
case BOOL:
if(*(bool *)(var1->data)){
return var1_ptr;
}else{
return var2_ptr;
}
break;
}
return temp_bool(false);
}
Variable ** negate(Variable ** var_ptr){
return temp_bool(!*(bool *)((*var_ptr)->data));
}
//Binary
Variable ** bitxor(Variable ** var1_ptr, Variable ** var2_ptr){
Variable * var1 = *var1_ptr;
Variable * var2 = *var2_ptr;
switch (var1->type) {
case INT:
switch (var2->type) {
case INT:
return temp_int(*(int64_t *)(var1->data) ^ *(int64_t *)(var2->data));
break;
case BOOL:
return temp_int(*(int64_t *)(var1->data) ^ *(bool *)(var2->data));
break;
}
break;
case BOOL:
switch (var2->type) {
case INT:
return temp_int(*(bool *)(var1->data) ^ *(int64_t *)(var2->data));
break;
case BOOL:
return temp_int(*(bool *)(var1->data) ^ *(bool *)(var2->data));
break;
}
break;
}
return temp_bool(false);
}
Variable ** bitor(Variable ** var1_ptr, Variable ** var2_ptr){
Variable * var1 = *var1_ptr;
Variable * var2 = *var2_ptr;
switch (var1->type) {
case INT:
switch (var2->type) {
case INT:
return temp_int(*(int64_t *)(var1->data) | *(int64_t *)(var2->data));
break;
case BOOL:
return temp_int(*(int64_t *)(var1->data) | *(bool *)(var2->data));
break;
}
break;
case BOOL:
switch (var2->type) {
case INT:
return temp_int(*(bool *)(var1->data) | *(int64_t *)(var2->data));
break;
case BOOL:
return temp_int(*(bool *)(var1->data) | *(bool *)(var2->data));
break;
}
break;
}
return temp_bool(false);
}
Variable ** bitand(Variable ** var1_ptr, Variable ** var2_ptr){
Variable * var1 = *var1_ptr;
Variable * var2 = *var2_ptr;
switch (var1->type) {
case INT:
switch (var2->type) {
case INT:
return temp_int(*(int64_t *)(var1->data) & *(int64_t *)(var2->data));
break;
case BOOL:
return temp_int(*(int64_t *)(var1->data) & *(bool *)(var2->data));
break;
}
break;
case BOOL:
switch (var2->type) {
case INT:
return temp_int(*(bool *)(var1->data) & *(int64_t *)(var2->data));
break;
case BOOL:
return temp_int(*(bool *)(var1->data) & *(bool *)(var2->data));
break;
}
break;
}
return temp_bool(false);
}
Variable ** shift_left(Variable ** var1_ptr, Variable ** var2_ptr){
Variable * var1 = *var1_ptr;
Variable * var2 = *var2_ptr;
switch (var1->type) {
case INT:
switch (var2->type) {
case INT:
return temp_int(*(int64_t *)(var1->data) << *(int64_t *)(var2->data));
break;
case BOOL:
return temp_int(*(int64_t *)(var1->data) << *(bool *)(var2->data));
break;
}
break;
case BOOL:
switch (var2->type) {
case INT:
return temp_int(*(bool *)(var1->data) << *(int64_t *)(var2->data));
break;
case BOOL:
return temp_int(*(bool *)(var1->data) << *(bool *)(var2->data));
break;
}
break;
}
return temp_bool(false);
}
Variable ** shift_right(Variable ** var1_ptr, Variable ** var2_ptr){
Variable * var1 = *var1_ptr;
Variable * var2 = *var2_ptr;
switch (var1->type) {
case INT:
switch (var2->type) {
case INT:
return temp_int(*(int64_t *)(var1->data) >> *(int64_t *)(var2->data));
break;
case BOOL:
return temp_int(*(int64_t *)(var1->data) >> *(bool *)(var2->data));
break;
}
break;
case BOOL:
switch (var2->type) {
case INT:
return temp_int(*(bool *)(var1->data) >> *(int64_t *)(var2->data));
break;
case BOOL:
return temp_int(*(bool *)(var1->data) >> *(bool *)(var2->data));
break;
}
break;
}
return temp_bool(false);
}
Variable ** bitnot(Variable ** var_ptr){
Variable * variable = *var_ptr;
switch (variable->type) {
case INT:
return temp_int(~*(int64_t *)(variable->data));
break;
case BOOL:
return temp_int(~*(bool *)(variable->data));
break;
}
return temp_bool(false);
}
//Comparison
bool c_less_than(Variable ** var1_ptr, Variable ** var2_ptr){
Variable * var1 = *var1_ptr;
Variable * var2 = *var2_ptr;
switch (var1->type) {
case INT:
switch (var2->type) {
case INT:
return (*(int64_t *)(var1->data) < *(int64_t *)(var2->data));
break;
case FLOAT:
return (*(int64_t *)(var1->data) < *(double *)(var2->data));
break;
case STRING:
return true;
break;
case NONE:
return false;
break;
case BOOL:
return (*(int64_t *)(var1->data) < *(bool *)(var2->data));
break;
}
break;
case FLOAT:
switch (var2->type) {
case INT:
return (*(double *)(var1->data) < *(int64_t *)(var2->data));
break;
case FLOAT:
return (*(double *)(var1->data) < *(double *)(var2->data));
break;
case STRING:
return true;
break;
case NONE:
return false;
break;
case BOOL:
return (*(double *)(var1->data) < *(bool *)(var2->data));
break;
}
break;
case STRING:
switch (var2->type) {
case INT:
return false;
break;
case FLOAT:
return false;
break;
case STRING:
return (strlen(var1->data) < strlen(var2->data));
break;
case NONE:
return false;
break;
case BOOL:
return false;
break;
}
break;
case NONE:
return !(var2->type == NONE);
break;
case BOOL:
switch (var2->type) {
case INT:
return (*(bool *)(var1->data) < (*(int64_t *)(var2->data) != 0));
break;
case FLOAT:
return (*(bool *)(var1->data) < (*(double *)(var2->data) != 0));
break;
case STRING:
return true;
break;
case NONE:
return false;
break;
case BOOL:
return (*(bool *)(var1->data) < *(bool *)(var2->data));
break;
}
break;
}
return false;
}
bool c_more_than(Variable ** var1_ptr, Variable ** var2_ptr){
Variable * var1 = *var1_ptr;
Variable * var2 = *var2_ptr;
switch (var1->type) {
case INT:
switch (var2->type) {
case INT:
return (*(int64_t *)(var1->data) > *(int64_t *)(var2->data));
break;
case FLOAT:
return (*(int64_t *)(var1->data) > *(double *)(var2->data));
break;
case STRING:
return false;
break;
case NONE:
return true;
break;
case BOOL:
return (*(int64_t *)(var1->data) > *(bool *)(var2->data));
break;
}
break;
case FLOAT:
switch (var2->type) {
case INT:
return (*(double *)(var1->data) > *(int64_t *)(var2->data));
break;
case FLOAT:
return (*(double *)(var1->data) > *(double *)(var2->data));
break;
case STRING:
return false;
break;
case NONE:
return true;
break;
case BOOL:
return (*(double *)(var1->data) > *(bool *)(var2->data));
break;
}
break;
case STRING:
switch (var2->type) {
case INT:
return true;
break;
case FLOAT:
return true;
break;
case STRING:
return (strlen(var1->data) > strlen(var2->data));
break;
case NONE:
return true;
break;
case BOOL:
return true;
break;
}
break;
case NONE:
return false;
break;
case BOOL:
switch (var2->type) {
case INT:
return (*(bool *)(var1->data) > (*(int64_t *)(var2->data) != 0));
break;
case FLOAT:
return (*(bool *)(var1->data) > (*(double *)(var2->data) != 0));
break;
case STRING:
return false;
break;
case NONE:
return true;
break;
case BOOL:
return (*(bool *)(var1->data) > *(bool *)(var2->data));
break;
}
break;
}
return false;
}
Variable ** less_than(int number, ...){
va_list args;
va_start(args,number);
Variable ** prior = NULL;
Variable ** this;
for(int x = 0; x < number; x++){
this = va_arg(args, Variable **);
if (prior != NULL) {
if (!c_less_than(prior, this)){
va_end(args);
return temp_bool(false);
}
}
prior = this;
}
va_end(args);
return temp_bool(true);
}
Variable ** more_than(int number, ...){
va_list args;
va_start(args,number);
Variable ** prior = NULL;
Variable ** this;
for(int x = 0; x < number; x++){
this = va_arg(args, Variable **);
if (prior != NULL) {
if (!c_more_than(prior, this)){
va_end(args);
return temp_bool(false);
}
}
prior = this;
}
va_end(args);
return temp_bool(true);
}
Variable ** less_than_or_equal(int number, ...){
va_list args;
va_start(args,number);
Variable ** prior = NULL;
Variable ** this;
for(int x = 0; x < number; x++){
this = va_arg(args, Variable **);
if (prior != NULL) {
if (!c_more_than(prior, this)){
va_end(args);
return temp_bool(true);
}
}
prior = this;
}
va_end(args);
return temp_bool(false);
}
Variable ** more_than_or_equal(int number, ...){
va_list args;
va_start(args,number);
Variable ** prior = NULL;
Variable ** this;
for(int x = 0; x < number; x++){
this = va_arg(args, Variable **);
if (prior != NULL) {
if (!c_less_than(prior, this)){
va_end(args);
return temp_bool(true);
}
}
prior = this;
}
va_end(args);
return temp_bool(false);
}
bool c_is_same(Variable ** var1_ptr, Variable ** var2_ptr){
Variable * var1 = *var1_ptr;
Variable * var2 = *var2_ptr;
if (var1->data == var2->data) {
//Data pointers are the same so the variables are considered identical in the python sense.
return true;
}else{
return false;
}
}
Variable ** is_same(int number, ...){
va_list args;
va_start(args,number);
Variable ** prior = NULL;
Variable ** this;
for(int x = 0; x < number; x++){
this = va_arg(args, Variable **);
if (prior != NULL) {
if (!c_is_same(prior, this)){
va_end(args);
return temp_bool(false);
}
}
prior = this;
}
va_end(args);
return temp_bool(true);
}
bool c_is_equal(Variable ** var1_ptr, Variable ** var2_ptr){
Variable * var1 = *var1_ptr;
Variable * var2 = *var2_ptr;
switch (var1->type) {
case INT:
switch (var2->type) {
case INT:
return (*(int64_t *)(var1->data) == *(int64_t *)(var2->data));
break;
case FLOAT:
return (*(int64_t *)(var1->data) == *(double *)(var2->data));
break;
case BOOL:
return ((*(int64_t *)(var1->data) != 0) == *(bool *)(var2->data));
break;
default:
return false;
break;
}
break;
case FLOAT:
switch (var2->type) {
case INT:
return (*(double *)(var1->data) == *(int64_t *)(var2->data));
break;
case FLOAT:
return (*(double *)(var1->data) == *(double *)(var2->data));
break;
case BOOL:
return ((*(double *)(var1->data) != 0) == *(bool *)(var2->data));
break;
default:
return false;
break;
}
break;
case STRING:
if (var2->type == STRING) {
return (strcmp(var1->data, var2->data) == 0);
}else{
return false;
}
break;
case NONE:
return (var2->type == NONE);
break;
case BOOL:
switch (var2->type) {
case INT:
return (*(bool *)(var1->data) == (*(int64_t *)(var2->data) != 0));
break;
case FLOAT:
return (*(bool *)(var1->data) == (*(double *)(var2->data) != 0));
break;
case BOOL:
return (*(bool *)(var1->data) == *(bool *)(var2->data));
break;
default:
return false;
break;
}
break;
}
return false;
}
Variable ** is_equal(int number, ...){
va_list args;
va_start(args,number);
Variable ** prior = NULL;
Variable ** this;
for(int x = 0; x < number; x++){
this = va_arg(args, Variable **);
if (prior != NULL) {
if (!c_is_equal(prior, this)){
va_end(args);
return temp_bool(false);
}
}
prior = this;
}
va_end(args);
return temp_bool(true);
}
Variable ** is_not_equal(int number, ...){
va_list args;
va_start(args,number);
Variable ** prior = NULL;
Variable ** this;
for(int x = 0; x < number; x++){
this = va_arg(args, Variable **);
if (prior != NULL) {
if (c_is_equal(prior, this)){
va_end(args);
return temp_bool(false);
}
}
prior = this;
}
va_end(args);
return temp_bool(true);
}
void delete_var(Variable ** variable){ //From python del statement to delete variables before emptying pool
//Free variable and data
Variable * var_ptr = *variable;
free(var_ptr->data);
free(var_ptr);
*variable = NULL; //change pointer to variable to NULL. This can only be done by passing in a pointer to the pointer.
}
void empty_pool(){ //Frees all data from variable pool
VarPool * var_pool = pool_stack[pool_stack_size-1]; //Current variable pool on top of stack
for (int x = 0; x < var_pool->size; x++) {
if(*var_pool->pool[x] != NULL){
free((*var_pool->pool[x])->data);//Free variable data
free(*var_pool->pool[x]); //Free variable
}
free(var_pool->pool[x]); //Free variable pointer
}
free(var_pool->pool); //Free pool variable array
free(var_pool); //Free variable pool structure
empty_temporary_pool(); //May not be done yet
pool_stack_size--;
pool_stack = realloc(pool_stack, pool_stack_size*sizeof(VarPool *));
//Free temporary pool and pop it off the stack
free(temp_pool_stack[pool_stack_size]->pool); //Free pool variable array
free(temp_pool_stack[pool_stack_size]); //Free variable pool structure
temp_pool_stack = realloc(temp_pool_stack, pool_stack_size*sizeof(VarPool *));
//Free string data and completely clear string pool
for (int x = 0; x < string_pool_size; x++) {
free(string_pool[x]);
}
string_pool_size = 0;
free(string_pool);
string_pool = NULL;
}
int main(){
init_pool_stack();
puts(string_val(add(temp_string("1 and "), add(temp_string("2"),temp_string(" and 3")))));
//Does almost the same as
//print "He" + "l"*((2**2)*2 >> 2) + ("o"*((4/2)-1) or True) + ("!" or False) + ""*((~6+5 & 1) and not True) + '!'*(4 ^ 6)
//But the add operator goes from right to left. It doesn't matter for this test
puts(string_val(add(temp_string("He"),add(multiply(temp_string("l"), shift_right(multiply(exponentiate(temp_int(2), temp_int(2)), temp_int(2)), temp_int(2))), add(or(multiply(temp_string("o"), subtract(divide(temp_int(4), temp_int(2)), temp_int(1))), temp_bool(true)), add(or(temp_string("!"), temp_bool(false)), add(multiply(temp_string(""), and(bitand(add(bitnot(temp_int(6)), temp_int(5)), temp_int(1)), negate(temp_bool(true)))), multiply(temp_string("!"), bitxor(temp_int(4), temp_int(6))))))))));
empty_pool(); //Finally empty globals pool which will deallocate pool_stack
return 0;
}