Files
RCBASIC4/rcbasic_build/identifier.h

1391 lines
41 KiB
C++
Executable File

#ifndef IDENTIFIER_H_INCLUDED
#define IDENTIFIER_H_INCLUDED
#include <inttypes.h>
#include <stack>
#include "rc_global.h"
#include "rc_utility.h"
#include "rc_debug.h"
//identifier structure information
//identifier types
#define ID_TYPE_NUM 1
#define ID_TYPE_STR 2
#define ID_TYPE_FN_NUM 3
#define ID_TYPE_FN_STR 4
#define ID_TYPE_BYREF_NUM 5
#define ID_TYPE_BYREF_STR 6
#define ID_TYPE_ARR_NUM 7
#define ID_TYPE_ARR_STR 8
#define ID_TYPE_SUB 9
#define ID_TYPE_USER 10
#define ID_TYPE_FN_USER 11
#define ID_TYPE_BYREF_USER 12
#define ID_TYPE_USER_NUM 13
#define ID_TYPE_USER_STR 14
#define ID_TYPE_USER_NUM_ARRAY 15
#define ID_TYPE_USER_STR_ARRAY 16
#define ID_TYPE_USER_ALL(id_index) ( id[id_index].type == ID_TYPE_USER || id[id_index].type == ID_TYPE_BYREF_USER || id[id_index].type == ID_TYPE_USER_NUM || id[id_index].type == ID_TYPE_USER_STR || id[id_index].type == ID_TYPE_USER_NUM_ARRAY || id[id_index].type == ID_TYPE_USER_STR_ARRAY )
#define BLOCK_STATE_MAIN 0
#define BLOCK_STATE_TYPE 1
#define BLOCK_STATE_FUNCTION 2
#define BLOCK_STATE_SUB 3
#define BLOCK_STATE_FOR 4
#define BLOCK_STATE_WHILE 5
#define BLOCK_STATE_DO 6
#define BLOCK_STATE_IF 7
#define BLOCK_STATE_SELECT 8
using namespace std;
string current_scope = "main";
int current_block_state = BLOCK_STATE_MAIN; //This hold different states depending on the type of block the program is currently in ie. type, function, sub, for, while, do, if, select
int current_type_index = 0;
int current_fn_index = 0;
bool isInFunctionScope = false;
int current_fn_id_count = 0;
uint64_t current_for_index = 0;
uint64_t current_while_index = 0;
uint64_t current_do_index = 0;
uint64_t current_if_index = 0;
uint64_t current_select_index = 0;
stack<int> block_state;
stack<string> for_end;
stack<uint64_t> for_counter;
stack<string> do_end;
stack<string> while_end;
bool isFunctionArg_flag = false;
bool enable_presets = true;
struct if_data
{
uint64_t index = 0;
uint64_t condition = 0;
bool else_set = false;
};
struct select_data
{
int case_type = ID_TYPE_NUM;
int index = 0;
int case_index = 0;
bool default_set = false;
bool case_set = false;
};
stack<if_data> if_block;
stack<select_data> select_block;
//array dimension structure
struct user_array_dim
{
int dim_size[3];
};
//user defined type structure
struct rc_type_description
{
uint32_t nidCount;
uint32_t nidDim;
uint32_t nidDimSize[3];
uint32_t sidCount;
uint32_t sidDim;
uint32_t sidDimSize[3];
uint32_t uidCount;
uint32_t uidDim;
uint32_t uidDimSize[3];
uint32_t uidTypeIndex;
};
struct user_type
{
string name; //name of the type
int num_members; //number of members
vector<string> member_name; //name of the members in the type
vector<int> member_type; //type of each member
vector<int> member_vec_pos; //the vector position for each member
int nidCount = 0;
int sidCount = 0;
int uidCount = 0;
vector<int> member_utype_index;
vector<int> member_dim_count; //number of dimensions for each member
vector<user_array_dim> member_dim; //size of each dimension in an array
};
struct fid_vector_entry
{
string vec_str;
int type;
};
//identifier structure
struct identifier
{
string name; //variable or function name
string scope; //the scope this identifier was created in
int type; //the identifier type, it will be one of the types above
int type_index; //if the identifier is a user_type, then this will be the index of the type within the utype vector
int num_args; //number of arguments in a function or number of dimensions in an array
uint64_t dim_size[3]; //size of each dimension in an array, up to 3 dimensions are supported
vector<string> fn_arg; //function argument name
vector<string> fn_reg;
vector<uint64_t> fn_arg_vec;
vector<int> fn_arg_type; //function argument type
vector<int> fn_arg_utype;
uint64_t vec_pos; //position in num, string, or user type vector for runtime
bool isBuiltin = false;
uint64_t vmFunctionIndex = 0;
bool isArrayArg = false;
vector<fid_vector_entry> fn_var;
bool isChild = false;
int parent_index = -1;
};
uint64_t current_vmFunction_index = 0;
vector<user_type> utype;
vector<identifier> id;
int num_id_count = 0;
int str_id_count = 0;
int usr_id_count = 0;
int fn_numCount = 0;
int fn_strCount = 0;
int fn_usrCount = 0;
int fn_byref_numCount = 0;
int fn_byref_strCount = 0;
int fn_byref_usrCount = 0;
int max_fn_numCount = 0;
int max_fn_strCount = 0;
int max_fn_usrCount = 0;
int max_fn_byref_numCount = 0;
int max_fn_byref_strCount = 0;
int max_fn_byref_usrCount = 0;
bool idExists(string id_name)
{
id_name = StringToUpper(id_name);
for(int i = 0; i < id.size(); i++)
{
if(id_name.compare(StringToUpper(id[i].name))==0)
return true;
}
return false;
}
bool matchCurrentScope(string id_scope, string check_scope = "")
{
string tmp_current_scope = "";
string tmp_id_scope = "";
int cs_i = 0;
int id_i = 0;
if(check_scope.compare("")==0)
check_scope = current_scope;
while(true)
{
tmp_current_scope = "";
tmp_id_scope = "";
for(; cs_i < check_scope.length(); cs_i++)
{
if(check_scope.substr(cs_i,1).compare(".")==0)
{
cs_i++;
break;
}
tmp_current_scope += check_scope.substr(cs_i,1);
}
for(; id_i < id_scope.length(); id_i++)
{
if(id_scope.substr(id_i,1).compare(".")==0)
{
id_i++;
break;
}
tmp_id_scope += id_scope.substr(id_i,1);
}
if(tmp_current_scope.compare(tmp_id_scope)!=0)
{
return false;
}
if(id_i == id_scope.length())
{
//cout << "SCOPE_MATCH: " << tmp_current_scope << " ~ " << tmp_id_scope << endl;
//cout << "INFO: " << id_scope << " ~ " << check_scope << endl;
return true;
}
}
return false;
}
bool idExistsInScope2(string id_name)
{
id_name = StringToLower(id_name);
int cs_start = 0;
int cs_length = 0;
bool match = true;
string id_scope = "";
for(int i = 0; i < id.size(); i++)
{
if(id_name.compare(StringToLower(id[i].name) )==0)
{
//cout << endl;
//cout << "ID found in: " << id[i].scope << endl;
//cout << "Current Scope: " << current_scope << endl;
//cout << endl;
//id has to exist in or above current scope
if(current_scope.length() < id[i].scope.length())
{
continue;
}
id_scope = "";
cs_start = 0;
cs_length = 0;
match = true;
//if(current_scope.find(id[i].scope)==0)
if(matchCurrentScope(id[i].scope))
{
//cout << id_name << " -> " << id[i].name << " : " << id[i].scope << " : " << current_scope << endl;
return true;
}
}
}
return false;
}
bool idExistsInScope(string id_name)
{
bool exists = idExistsInScope2(id_name);
if(!exists)
{
if(id_name.substr(id_name.length()-1,1).compare("$")==0)
exists = idExistsInScope2(id_name.substr(0, id_name.length()-1));
else
exists = idExistsInScope2(id_name + "$");
}
return exists;
}
void output_vars()
{
for(int i = 0; i < id.size(); i++)
{
cout << endl;
cout << "id: " << id[i].name << " : " << id[i].vec_pos << endl;
cout << "type: " << id[i].type << endl;
if(id[i].type == ID_TYPE_USER)
cout << "type_id: " << utype[id[i].type_index].name << endl;
cout << "scope: " << id[i].scope << endl;
cout << "dim: " << id[i].num_args << endl;
for(int n = 0; n < id[i].num_args; n++)
cout << "dim[" << n << "] = " << id[i].dim_size[n] << endl;
}
cout << endl;
}
int getUType(string utype_name)
{
string param = utype_name;
utype_name = StringToLower(utype_name);
for(int i = 0; i < utype.size(); i++)
{
//cout << "TYPE[" << i << "] = " << utype[i].name << endl;
if(utype_name.compare(StringToLower(utype[i].name))==0)
{
return i;
}
}
rc_setError(param + " does not name a type");
return -1;
}
bool create_type(string utype_name)
{
utype_name = StringToLower(utype_name);
if(isKeyWord(utype_name) || idExistsInScope(utype_name))
{
rc_setError(utype_name + " is not a valid identifier");
return false;
}
else if(getUType(utype_name)>=0)
{
rc_setError(utype_name + " already exists");
return false;
}
current_type_index = utype.size();
//cout << "current type_index = " << current_type_index << endl;
user_type ut;
ut.name = utype_name;
ut.num_members = 0;
utype.push_back(ut);
return true;
}
bool memberExists(string member_name)
{
member_name = StringToLower(member_name);
for(int i = 0; i < utype[current_type_index].num_members; i++)
{
if(StringToLower(utype[current_type_index].member_name[i]).compare(member_name)==0)
return true;
}
return false;
}
bool add_type_member(string member_name, int member_type, string member_utype_name, int member_dim_count, string dim1 = "n0", string dim2 = "n0", string dim3 = "n0")
{
int m_utype_index = member_utype_name.compare("")!=0 ? getUType(member_utype_name) : -1;
//cout << "m_utype_index = " << m_utype_index << " : " << member_utype_name << endl;
if((member_utype_name.compare("")!=0) && m_utype_index < 0)
{
rc_setError(member_utype_name + " does not name a valid type");
return false;
}
if(m_utype_index == current_type_index)
{
//cout << "you canno do is" << endl;
rc_setError("Cannot create member of type from within itself");
return false;
}
//cout << "utype index = " << current_type_index << endl;
int utype_index = current_type_index;
int utype_current_member = utype[utype_index].num_members;
member_name = StringToLower(member_name);
utype[utype_index].member_name.push_back(member_name);
string dim_mem_type = "";
switch(member_type)
{
case ID_TYPE_NUM:
dim_mem_type = "!0 !" + rc_intToString(utype_current_member);
utype[utype_index].member_type.push_back(ID_TYPE_USER_NUM);
utype[utype_index].member_vec_pos.push_back(utype[utype_index].nidCount);
utype[utype_index].nidCount++;
break;
case ID_TYPE_ARR_NUM:
dim_mem_type = "!0 !" + rc_intToString(utype_current_member);
utype[utype_index].member_type.push_back(ID_TYPE_USER_NUM_ARRAY);
utype[utype_index].member_vec_pos.push_back(utype[utype_index].nidCount);
utype[utype_index].nidCount++;
break;
case ID_TYPE_STR:
dim_mem_type = "!1 !" + rc_intToString(utype_current_member);
utype[utype_index].member_type.push_back(ID_TYPE_USER_STR);
utype[utype_index].member_vec_pos.push_back(utype[utype_index].sidCount);
utype[utype_index].sidCount++;
break;
case ID_TYPE_ARR_STR:
dim_mem_type = "!1 !" + rc_intToString(utype_current_member);
utype[utype_index].member_type.push_back(ID_TYPE_USER_STR_ARRAY);
utype[utype_index].member_vec_pos.push_back(utype[utype_index].sidCount);
utype[utype_index].sidCount++;
break;
case ID_TYPE_USER:
dim_mem_type = "!2 !" + rc_intToString(utype_current_member);
utype[utype_index].member_type.push_back(ID_TYPE_USER);
utype[utype_index].member_vec_pos.push_back(utype[utype_index].uidCount);
utype[utype_index].uidCount++;
break;
default:
rc_setError("Invalid member type in type definition");
return false;
break;
}
utype[utype_index].member_dim_count.push_back(member_dim_count);
utype[utype_index].member_utype_index.push_back(m_utype_index);
dim1 = dim1.compare("")==0 ? "n0" : dim1;
dim2 = dim2.compare("")==0 ? "n0" : dim2;
dim3 = dim3.compare("")==0 ? "n0" : dim3;
vm_asm.push_back("dim_tfield !" + rc_intToString(utype_index) + " " + dim_mem_type + " !"
+ rc_intToString(member_dim_count) + " "
+ dim1 + " " + dim2 + " " + dim3);
//NOTE: user_array_dim is no longer used
user_array_dim d;
//d.dim_size[0] = dim1;
//d.dim_size[1] = dim2;
//d.dim_size[2] = dim3;
utype[utype_index].member_dim.push_back(d);
//cout << member_name << " has " << member_dim_count << " dimensions" << endl;
//utype[utype_index].member_dim[utype_current_member].dim_size[1] = dim2;
//utype[utype_index].member_dim[utype_current_member].dim_size[2] = dim3;
utype[utype_index].num_members++;
return true;
}
bool add_type_member_embedded(string member_name, int member_type, string member_utype_name, int member_dim_count, int dim1, int dim2, int dim3)
{
int m_utype_index = member_utype_name.compare("")!=0 ? getUType(member_utype_name) : -1;
if(m_utype_index == current_type_index)
{
//cout << "you canno do is" << endl;
rc_setError("Cannot create member of type from within itself");
return false;
}
//cout << "utype index = " << current_type_index << endl;
int utype_index = current_type_index;
int utype_current_member = utype[utype_index].num_members;
member_name = StringToLower(member_name);
utype[utype_index].member_name.push_back(member_name);
string dim_mem_type = "";
switch(member_type)
{
case ID_TYPE_NUM:
dim_mem_type = "!0 !" + rc_intToString(utype_current_member);
utype[utype_index].member_type.push_back(ID_TYPE_USER_NUM);
utype[utype_index].member_vec_pos.push_back(utype[utype_index].nidCount);
utype[utype_index].nidCount++;
break;
case ID_TYPE_ARR_NUM:
dim_mem_type = "!0 !" + rc_intToString(utype_current_member);
utype[utype_index].member_type.push_back(ID_TYPE_USER_NUM_ARRAY);
utype[utype_index].member_vec_pos.push_back(utype[utype_index].nidCount);
utype[utype_index].nidCount++;
break;
case ID_TYPE_STR:
dim_mem_type = "!1 !" + rc_intToString(utype_current_member);
utype[utype_index].member_type.push_back(ID_TYPE_USER_STR);
utype[utype_index].member_vec_pos.push_back(utype[utype_index].sidCount);
utype[utype_index].sidCount++;
break;
case ID_TYPE_ARR_STR:
dim_mem_type = "!1 !" + rc_intToString(utype_current_member);
utype[utype_index].member_type.push_back(ID_TYPE_USER_STR_ARRAY);
utype[utype_index].member_vec_pos.push_back(utype[utype_index].sidCount);
utype[utype_index].sidCount++;
break;
case ID_TYPE_USER:
dim_mem_type = "!2 !" + rc_intToString(utype_current_member);
utype[utype_index].member_type.push_back(ID_TYPE_USER);
utype[utype_index].member_vec_pos.push_back(utype[utype_index].uidCount);
utype[utype_index].uidCount++;
break;
default:
rc_setError("Invalid member type in type definition");
return false;
break;
}
utype[utype_index].member_dim_count.push_back(member_dim_count);
utype[utype_index].member_utype_index.push_back(m_utype_index);
vm_asm.push_back("dim_tfield !" + rc_intToString(utype_index) + " " + dim_mem_type + " !"
+ rc_intToString(member_dim_count) + " "
+ "n0 n1 n2");
//NOTE: user_array_dim is no longer used
user_array_dim d;
d.dim_size[0] = dim1;
d.dim_size[1] = dim2;
d.dim_size[2] = dim3;
utype[utype_index].member_dim.push_back(d);
//cout << member_name << " has " << member_dim_count << " dimensions" << endl;
//utype[utype_index].member_dim[utype_current_member].dim_size[1] = dim2;
//utype[utype_index].member_dim[utype_current_member].dim_size[2] = dim3;
utype[utype_index].num_members++;
return true;
}
//return the index of the id name or -1 on failure
int getIDInScope_ByIndex_TypeMatch(string id_name, string check_scope="")
{
id_name = StringToLower(id_name);
int cs_start = 0;
int cs_length = 0;
bool match = true;
string id_scope = "";
if(check_scope.compare("")==0)
check_scope = current_scope;
int scope_match = 0;
int tmp_match = 0;
int id_match = -1;
check_scope = StringToLower(check_scope);
//cout << "CHECK SCOPE = " << check_scope << endl;
string id_name_str = "";
if(id_name.substr(id_name.length()-1,1).compare("$")==0)
{
id_name_str = id_name;
}
else
{
id_name_str = id_name + "$";
}
for(int i = 0; i < id.size(); i++)
{
string id_cmp_scope = StringToLower(id[i].scope);
if(id_cmp_scope.compare(check_scope)==0)
{
if(id[i].name.substr(id[i].name.length()-1,1).compare("$")==0) //id in type is string
{
//cout << id_name_str << " ~ " << id[i].name << endl;
if(id_name_str.compare(StringToLower(id[i].name))==0)
return i;
}
else
{
//cout << id_name << " ~ " << id[i].name << " scope: " << check_scope << endl;
if(id_name.compare(StringToLower(id[i].name))==0)
return i;
}
}
}
return id_match;
}
//return the index of the id name or -1 on failure
int getIDInScope_ByIndex2(string id_name, string check_scope="")
{
id_name = StringToLower(id_name);
int cs_start = 0;
int cs_length = 0;
bool match = true;
string id_scope = "";
if(check_scope.compare("")==0)
check_scope = current_scope;
int scope_match = 0;
int tmp_match = 0;
int id_match = -1;
for(int i = 0; i < id.size(); i++)
{
//if(StringToLower(id_name).compare("tst")==0 && StringToLower(id[i].name.substr(0,1)).compare("t")==0)
// cout << "CMP: " << id_name << " to " << id[i].name << endl;
if(id_name.compare(StringToLower(id[i].name))==0)
{
//cout << endl;
//cout << "ID_NAME = " << id[i].name << endl;
//cout << "ID found in: " << id[i].scope << endl;
//cout << "Current Scope: " << check_scope << endl;
//cout << endl;
//id has to exist in or above current scope
if(check_scope.length() < id[i].scope.length())
{
//cout << "SCOPE CHECK: " << check_scope.length() << " <> " << id[i].scope.length() << endl;
continue;
}
//if(current_scope.find(id[i].scope)==0)
if(matchCurrentScope(id[i].scope, check_scope))
{
//cout << "FOUND MATCH FOR [" << id[i].name << "] : " << id[i].vec_pos << " ; " << id[i].scope << " : t=" << id[i].type << endl << endl;
return i;
}
}
}
return id_match;
}
int getIDInScope_ByIndex(string id_name, string check_scope="")
{
int id_index = getIDInScope_ByIndex2(id_name, check_scope);
if(id_index < 0)
{
if(id_name.substr(id_name.length()-1,1).compare("$")==0)
id_index = getIDInScope_ByIndex2(id_name.substr(0, id_name.length()-1), check_scope);
else
id_index = getIDInScope_ByIndex2(id_name + "$", check_scope);
}
return id_index;
}
//return the index of the id name or -1 on failure
int getIDInScope2(string id_name, string check_scope="")
{
id_name = StringToLower(id_name);
int cs_start = 0;
int cs_length = 0;
bool match = true;
string id_scope = "";
if(check_scope.compare("")==0)
check_scope = current_scope;
int scope_match = 0;
int tmp_match = 0;
int id_match_vecpos = -1;
for(int i = 0; i < id.size(); i++)
{
if(id_name.compare(StringToLower(id[i].name))==0 || id[i].name.compare(id_name+"$")==0)
{
//cout << endl;
//cout << "ID_NAME = " << id[i].name << endl;
//cout << "ID found in: " << id[i].scope << endl;
//cout << "Current Scope: " << check_scope << endl;
//cout << endl;
//id has to exist in or above current scope
if(check_scope.length() < id[i].scope.length())
{
continue;
}
//if(current_scope.find(id[i].scope)==0)
if(matchCurrentScope(id[i].scope, check_scope))
{
//cout << "FOUND MATCH FOR [" << id[i].name << "] : " << id[i].vec_pos << " ; " << id[i].scope << endl;
return id[i].vec_pos;
}
}
}
return id_match_vecpos;
}
int getIDInScope(string id_name, string check_scope="")
{
if(check_scope.compare("")==0)
check_scope = current_scope;
int id_vec = getIDInScope2(id_name, check_scope);
if(id_vec < 0)
{
if(id_name.substr(id_name.length()-1,1).compare("$")==0)
id_vec = getIDInScope2(id_name.substr(0, id_name.length()-1), check_scope);
else
id_vec = getIDInScope2(id_name + "$", check_scope);
}
return id_vec;
}
bool isValidIDName(string name)
{
name = StringToLower(name);
if(name.compare("")==0)
return false;
if(name.substr(name.length()-1,1).compare("$")==0)
{
name = name.substr(0, name.length()-1);
if(name.compare("")==0)
return false;
}
if(!isalpha(name[0]))
return false;
for(int i = 0; i < name.length(); i++)
{
if( (!isalnum(name[i])) && (name.substr(i,1).compare("_")!=0) )
return false;
}
if(isKeyWord(name))
return false;
return true;
}
void set_vectorPosition(identifier &var, bool isMember = false, int utype_index = 0, int member_index = 0)
{
if(isMember)
{
var.vec_pos = utype[utype_index].member_vec_pos[member_index];
return;
}
if(var.type == ID_TYPE_ARR_NUM || var.type == ID_TYPE_NUM || var.type == ID_TYPE_BYREF_NUM)
{
var.vec_pos = num_id_count;
num_id_count++;
}
else if(var.type == ID_TYPE_STR || var.type == ID_TYPE_ARR_STR || var.type == ID_TYPE_BYREF_STR)
{
var.vec_pos = str_id_count;
str_id_count++;
}
else if(var.type == ID_TYPE_USER || var.type == ID_TYPE_BYREF_USER)
{
var.vec_pos = usr_id_count;
usr_id_count++;
}
}
int get_vectorPosition(string scope, string id_name)
{
return -1;
}
bool id_emit(identifier var, string dim1="_", string dim2="_", string dim3="_")
{
//alloc_xxx ID, DIM_COUNT, DIM1_SIZE, DIM2_SIZE, DIM3_SIZE
string emit_asm = "";
string var_id = "";
string dim_count = "";
string dim_size[3];
if(var.type == ID_TYPE_ARR_NUM)
{
if(var.num_args > 0)
{
emit_asm += rc_intToString(var.num_args);
if(var.num_args == 1 && dim1.substr(0,1).compare("n")==0)
emit_asm = "dim_num1 ";
else if(var.num_args == 2 && dim1.substr(0,1).compare("n")==0 && dim2.substr(0,1).compare("n")==0)
emit_asm = "dim_num2 ";
else if(var.num_args == 3 && dim1.substr(0,1).compare("n")==0 && dim2.substr(0,1).compare("n")==0 && dim3.substr(0,1).compare("n")==0)
emit_asm = "dim_num3 ";
else
{
rc_setError("Invalid number of arguments for " + var.name);
return false;
}
}
else
{
rc_setError("Must have atleast 1 dimension in array");
}
var_id = rc_intToString(getIDInScope(var.name, var.scope));
emit_asm += "!" + var_id + " ";
if(var.num_args == 1)
emit_asm += dim1;
else if(var.num_args == 2)
emit_asm += dim1 + " " + dim2;
else if(var.num_args == 3)
emit_asm += dim1 + " " + dim2 + " " + dim3;
vm_asm.push_back(emit_asm);
return true;
}
else if(var.type == ID_TYPE_ARR_STR)
{
if(var.num_args > 0)
{
emit_asm += rc_intToString(var.num_args);
if(var.num_args == 1 && dim1.substr(0,1).compare("n")==0)
emit_asm = "dim_str1 ";
else if(var.num_args == 2 && dim1.substr(0,1).compare("n")==0 && dim2.substr(0,1).compare("n")==0)
emit_asm = "dim_str2 ";
else if(var.num_args == 3 && dim1.substr(0,1).compare("n")==0 && dim2.substr(0,1).compare("n")==0 && dim3.substr(0,1).compare("n")==0)
emit_asm = "dim_str3 ";
else
{
rc_setError("Invalid number of arguments for " + var.name);
return false;
}
}
else
{
rc_setError("Must have atleast 1 dimension in array");
}
var_id = rc_intToString(getIDInScope(var.name, var.scope));
emit_asm += "!" + var_id + " ";
if(var.num_args == 1)
emit_asm += dim1;
else if(var.num_args == 2)
emit_asm += dim1 + " " + dim2;
else if(var.num_args == 3)
emit_asm += dim1 + " " + dim2 + " " + dim3;
vm_asm.push_back(emit_asm);
return true;
}
else if(var.type == ID_TYPE_USER)
{
emit_asm = "dim_type ";
if(var.num_args > 0)
{
emit_asm += rc_intToString(var.num_args);
if(var.num_args == 1 && dim1.substr(0,1).compare("n")==0)
emit_asm = "dim_type1 ";
else if(var.num_args == 2 && dim1.substr(0,1).compare("n")==0 && dim2.substr(0,1).compare("n")==0)
emit_asm = "dim_type2 ";
else if(var.num_args == 3 && dim1.substr(0,1).compare("n")==0 && dim2.substr(0,1).compare("n")==0 && dim3.substr(0,1).compare("n")==0)
emit_asm = "dim_type3 ";
else
{
rc_setError("Invalid number of arguments for " + var.name);
return false;
}
}
var_id = rc_intToString(getIDInScope(var.name, var.scope));
emit_asm += "!" + var_id + " !" + rc_intToString(var.type_index) + " ";
if(var.num_args == 1)
emit_asm += dim1;
else if(var.num_args == 2)
emit_asm += dim1 + " " + dim2;
else if(var.num_args == 3)
emit_asm += dim1 + " " + dim2 + " " + dim3;
vm_asm.push_back(emit_asm);
return true;
}
else
{
//rc_setError("Could not identify type");
//return false;
}
return true;
}
bool create_type_members(int id_index, int type_index)
{
//cout << "start type_member" << endl;
//cout << "id_index = " << id_index << endl;
//cout << "utype_index = " << id[id_index].type_index << endl;
//cout << "num_members = " << utype[0].num_members << endl;
identifier var;
int utype_index = id[id_index].type_index;
int member_index = 0;
user_array_dim d;
if( (id_index < 0 || id_index >= id.size()) || (utype_index < 0 || utype_index >= utype.size()) )
return true;
for(int i = 0; i < utype[utype_index].num_members; i++)
{
member_index = id.size();
var.name = StringToLower(utype[utype_index].member_name[i]);
var.type = utype[utype_index].member_type[i];
var.type_index = utype[utype_index].member_utype_index[i];
var.isChild = true;
var.parent_index = id_index;
set_vectorPosition(var, true, utype_index, i);
//cout << "vec -> " << var.vec_pos << endl;
var.scope = StringToLower(id[id_index].scope + "." + id[id_index].name);
var.num_args = utype[utype_index].member_dim_count[i];
var.dim_size[0] = utype[utype_index].member_dim[i].dim_size[0];
var.dim_size[1] = utype[utype_index].member_dim[i].dim_size[1];
var.dim_size[2] = utype[utype_index].member_dim[i].dim_size[2];
//cout << "member = " << var.name << " : " << var.vec_pos << endl;
//cout << "member_type = " << var.type << endl;
//cout << "member_type_index = " << var.type_index << endl;
id.push_back(var);
//id_emit(var);
if(var.type = ID_TYPE_USER)
{
if(!create_type_members(member_index, var.type_index))
{
rc_setError("Could not create member " + var.name + " inside " + var.scope);
return false;
}
}
}
//cout << "end type_member" << endl;
return true;
}
bool create_variable(string name, int type, string utype_name="", int vec = -1)
{
identifier var;
var.name = name;
var.type = type;
var.isArrayArg = false;
if(name.substr(0,1).compare("#")==0)
var.scope = "main";
else
var.scope = current_scope;
if(var.type == ID_TYPE_USER || var.type == ID_TYPE_BYREF_USER)
{
var.type_index = getUType(utype_name);
if(var.type_index < 0)
{
rc_setError("Type \"" + utype_name +"\" does not exists");
return false;
}
int var_index = id.size();
var.num_args = 0;
var.parent_index = -1;
if(vec == -1)
{
set_vectorPosition(var);
//cout << var.name << " <==> " << var.vec_pos << endl;
}
else
{
//cout << "set " << name << " to " << vec << endl;
var.vec_pos = vec;
}
id.push_back(var);
if(isInFunctionScope && !isFunctionArg_flag)
{
vm_asm.push_back("preset_t !" + rc_intToString(var.vec_pos) + " !" + rc_intToString(var.type_index));
}
else if(!isFunctionArg_flag)
id_emit(var);
//create all sub variables here
create_type_members(var_index, var.type_index);
}
else
{
var.num_args = 0;
if(vec == -1)
{
set_vectorPosition(var);
//cout << var.name << " <==> " << var.vec_pos << endl;
}
else
{
//cout << "set " << name << " to " << vec << endl;
var.vec_pos = vec;
}
id.push_back(var);
id_emit(var);
}
if(isInFunctionScope && !isFunctionArg_flag)
{
if(var.type == ID_TYPE_NUM || var.type == ID_TYPE_ARR_NUM)
vm_asm.push_back("preset !" + rc_intToString(var.vec_pos) );
else if(var.type == ID_TYPE_STR || var.type == ID_TYPE_ARR_STR)
vm_asm.push_back("preset$ !" + rc_intToString(var.vec_pos));
}
isFunctionArg_flag = false;
return true;
}
bool create_array(string name, int type, string utype_name, int dim_count, string dim1="", string dim2="", string dim3="", int vec = -1)
{
identifier var;
var.name = name;
var.type = type;
var.scope = current_scope;
var.isArrayArg = false;
if(var.type == ID_TYPE_USER)
{
var.type_index = getUType(utype_name);
if(var.type_index < 0)
{
rc_setError(utype_name + " does not name a type");
return false;
}
var.num_args = dim_count;
if(dim_count < 1 || dim_count > 3)
{
rc_setError("Array must be in the range of 1 to 3 dimensions");
return false;
}
int var_index = id.size();
set_vectorPosition(var);
id.push_back(var);
if(isInFunctionScope)
{
switch(var.num_args)
{
case 0:
vm_asm.push_back("preset_t !" + rc_intToString(var.vec_pos) + " !" + rc_intToString(var.type_index));
break;
case 1:
vm_asm.push_back("preset_t1 !" + rc_intToString(var.vec_pos) + " !" + rc_intToString(var.type_index) + " " + dim1);
break;
case 2:
vm_asm.push_back("preset_t2 !" + rc_intToString(var.vec_pos) + " !" + rc_intToString(var.type_index) + " " + dim1 + " " + dim2);
break;
case 3:
vm_asm.push_back("preset_t3 !" + rc_intToString(var.vec_pos) + " !" + rc_intToString(var.type_index) + " " + dim1 + " " + dim2 + " " + dim3);
break;
}
}
else
id_emit(var, dim1, dim2, dim3);
//create all sub variables here
create_type_members(var_index, var.type_index);
}
else
{
var.num_args = dim_count;
if(dim_count < 1 || dim_count > 3)
{
rc_setError("Array must be in the range of 1 to 3 dimensions");
return false;
}
if(vec == -1)
{
set_vectorPosition(var);
id.push_back(var);
id_emit(var, dim1, dim2, dim3);
}
else
{
var.vec_pos = vec;
id.push_back(var);
}
}
if((isInFunctionScope && !isFunctionArg_flag) && enable_presets)
{
if(var.type == ID_TYPE_NUM || var.type == ID_TYPE_ARR_NUM)
vm_asm.push_back("preset !" + rc_intToString(var.vec_pos) );
else if(var.type == ID_TYPE_STR || var.type == ID_TYPE_ARR_STR)
vm_asm.push_back("preset$ !" + rc_intToString(var.vec_pos));
}
isFunctionArg_flag = false;
return true;
}
bool embed_function(string name, int type, int fn_utype=-1)
{
if(getIDInScope(name) >= 0)
{
rc_setError("Identifier [" + name + "] already exists in this scope");
return false;
}
current_scope = "main." + name;
isInFunctionScope = true;
switch(type)
{
case ID_TYPE_SUB:
current_block_state = BLOCK_STATE_SUB;
break;
case ID_TYPE_FN_NUM:
case ID_TYPE_FN_STR:
case ID_TYPE_FN_USER:
current_block_state = BLOCK_STATE_FUNCTION;
break;
default:
rc_setError("Invalid type for function definition");
return false;
}
fn_numCount = 0;
fn_strCount = 0;
fn_usrCount = 0;
fn_byref_numCount = 0;
fn_byref_strCount = 0;
fn_byref_usrCount = 0;
identifier fn;
fn.name = name;
fn.scope = "main";
fn.type = type;
fn.type_index = fn_utype;
fn.isBuiltin = true;
fn.vmFunctionIndex = current_vmFunction_index;
current_vmFunction_index++;
//cout << "current_vmFunction = " << current_vmFunction_index << endl;
fn.num_args = 0; //function args default to 0; args are added with add_function_args
current_fn_index = id.size();
id.push_back(fn);
return true;
}
bool add_embedded_arg(string arg_name, int arg_type, int arg_utype=-1)
{
//fn_arg
//fn_arg_type
//fn_arg_utype
int fn_index = current_fn_index;
id[fn_index].fn_arg.push_back(arg_name);
id[fn_index].fn_arg_type.push_back(arg_type);
id[fn_index].fn_arg_utype.push_back(arg_utype);
string fn_arg_utype_name = "";
if(arg_utype >= 0)
fn_arg_utype_name = utype[arg_utype].name;
string fn_id = "";
int fn_id_index = -1;
if(arg_type == ID_TYPE_NUM)
{
fn_id = "#fn" + rc_intToString(fn_numCount);
if(getIDInScope(fn_id) < 0)
create_variable(fn_id, ID_TYPE_NUM, "");
fn_numCount++;
}
else if(arg_type == ID_TYPE_STR)
{
fn_id = "#fs" + rc_intToString(fn_strCount);
if(getIDInScope(fn_id) < 0)
create_variable(fn_id, ID_TYPE_STR);
fn_strCount++;
}
else if(arg_type == ID_TYPE_USER)
{
fn_id = "#fu" + rc_intToString(fn_usrCount);
if(getIDInScope(fn_id) < 0)
create_variable(fn_id, ID_TYPE_USER, fn_arg_utype_name);
fn_usrCount++;
}
else if(arg_type == ID_TYPE_BYREF_NUM)
{
fn_id = "#fn" + rc_intToString(fn_numCount);
if(getIDInScope(fn_id) < 0)
create_variable(fn_id, ID_TYPE_BYREF_NUM);
fn_numCount++;
}
else if(arg_type == ID_TYPE_BYREF_STR)
{
fn_id = "#fs" + rc_intToString(fn_strCount);
if(getIDInScope(fn_id) < 0)
create_variable(fn_id, ID_TYPE_BYREF_STR);
fn_strCount++;
}
else if(arg_type == ID_TYPE_BYREF_USER)
{
fn_id = "#fu" + rc_intToString(fn_usrCount);
if(getIDInScope(fn_id) < 0)
create_variable(fn_id, ID_TYPE_BYREF_USER, fn_arg_utype_name);
fn_usrCount++;
}
else
{
rc_setError("Invalid type in function definition");
return false;
}
int fn_arg_vec = getIDInScope(fn_id);
//cout << fn_id << " ====> " << fn_arg_vec << endl;
isFunctionArg_flag = true;
create_variable(arg_name, arg_type, fn_arg_utype_name, fn_arg_vec);
id[fn_index].fn_reg.push_back( fn_id );
id[fn_index].fn_arg_vec.push_back(fn_arg_vec);
id[fn_index].num_args++;
fid_vector_entry f_entry;
f_entry.type = arg_type;
f_entry.vec_str = "!" + rc_intToString(fn_arg_vec);
id[fn_index].fn_var.push_back( f_entry );
return true;
}
bool create_function(string name, int type, string utype_name)
{
if(getIDInScope(name) >= 0)
{
rc_setError("Identifier [" + name + "] already exists in this scope");
return false;
}
current_scope += "." + name;
isInFunctionScope = true;
current_fn_id_count = 0;
switch(type)
{
case ID_TYPE_SUB:
current_block_state = BLOCK_STATE_SUB;
break;
case ID_TYPE_FN_NUM:
case ID_TYPE_FN_STR:
current_block_state = BLOCK_STATE_FUNCTION;
break;
case ID_TYPE_FN_USER:
current_block_state = BLOCK_STATE_FUNCTION;
break;
default:
rc_setError("Invalid type for function definition");
return false;
}
fn_numCount = 0;
fn_strCount = 0;
fn_usrCount = 0;
fn_byref_numCount = 0;
fn_byref_strCount = 0;
fn_byref_usrCount = 0;
vm_asm.push_back(".data");
vm_asm.push_back("label " + name);
identifier fn;
fn.name = name;
fn.scope = "main";
fn.type = type;
fn.type_index = getUType(utype_name);
if(type == ID_TYPE_FN_USER && fn.type_index < 0)
{
rc_setError("Type \"" + utype_name + "\" does not exists");
return false;
}
fn.isBuiltin = false;
fn.isArrayArg = false;
fn.fn_var.clear();
int id_index = id.size();
fn.num_args = 0; //function args default to 0; args are added with add_function_args
current_fn_index = id.size();
id.push_back(fn);
if(fn.type == ID_TYPE_FN_USER)
create_type_members(id_index, fn.type_index);
return true;
}
bool add_function_arg(string arg_name, int arg_type, string utype_name)
{
//fn_arg
//fn_arg_type
//fn_arg_utype
int fn_index = current_fn_index;
id[fn_index].fn_arg.push_back(arg_name);
id[fn_index].fn_arg_type.push_back(arg_type);
isFunctionArg_flag = true;
//cout << "ARG = " << arg_name << " type = " << arg_type << endl;
if(!create_variable(arg_name, arg_type, utype_name))
{
rc_setError("Invalid argument in Function definition");
return false;
}
//id[fn_index].fn_reg.push_back( fn_id );
int arg_id_vec = getIDInScope(arg_name);
int arg_id_index = getIDInScope_ByIndex(arg_name);
if(arg_id_index < 0)
{
rc_setError("Could not create argument of type \"" + utype_name + "\"");
return false;
}
id[fn_index].fn_arg_vec.push_back( arg_id_vec );
id[fn_index].fn_arg_utype.push_back( id[arg_id_index].type_index );
id[fn_index].num_args++;
return true;
}
bool create_function_variable(string arg_name, int arg_type, string utype_name="")
{
//fn_arg
//fn_arg_type
//fn_arg_utype
int fn_index = current_fn_index;
create_variable(arg_name, arg_type, utype_name);
return true;
}
bool create_function_array(string arg_name, int arg_type, int dim_count, string dim1, string dim2, string dim3)
{
//fn_arg
//fn_arg_type
//fn_arg_utype
int fn_index = current_fn_index;
create_array(arg_name, arg_type, "", dim_count, dim1, dim2, dim3);
return true;
}
bool set_scope(string scope)
{
current_scope = scope;
return false;
}
bool exit_scope(int num_levels)
{
if(num_levels <= 0)
return false;
int lv = 0;
string scope = current_scope;
for(int i = scope.length()-1; i > 0; i--)
{
if(scope.substr(i,1).compare(".")==0)
{
lv++;
scope = scope.substr(0,i);
if(lv==num_levels)
{
current_scope = scope;
return true;
}
}
}
current_scope = scope;
return false;
}
bool enter_scope(string sub_scope)
{
return false;
}
int getIDIndex(string id_name)
{
id_name = StringToLower(id_name);
for(int i = 0; i < id.size(); i++)
{
if(id[i].name.compare(id_name)==0)
return i;
}
return -1;
}
/*type definitions header
-------------------------------
num types
type #1 num fields
field #1 type (0 - num, 1 - str, 3 - udt)
field #1 num dimensions
...
field #<num fields> type (0 - num, 1 - str, 3 - udt)
field #<num fields> num dimensions
type #<num types> num fields
field #1 type (0 - num, 1 - str, 3 - udt)
field #1 num dimensions
...
field #<num fields> type (0 - num, 1 - str, 3 - udt)
field #<num fields> num dimensions
*/
#endif // IDENTIFIER_H_INCLUDED