289 lines
7.9 KiB
C++
289 lines
7.9 KiB
C++
#include <string>
|
|
#include <functional>
|
|
#include <iostream>
|
|
#include <cmath>
|
|
|
|
#include "common.hpp"
|
|
#include "keywords.hpp"
|
|
|
|
const std::vector<Keyword> keywords =
|
|
{
|
|
{
|
|
.name = "print",
|
|
.expected_num_args = -1,
|
|
.expected_token_types = {TokenType::ID_OR_LIT},
|
|
.expected_value_types = {ValueType::ANY},
|
|
.func = [](Runtime& rt, const std::vector<Token>& tokens)
|
|
{
|
|
for(auto& arg : tokens)
|
|
{
|
|
if(arg.type == TokenType::LITERAL)
|
|
{
|
|
if(arg.value_type == ValueType::STRING)
|
|
std::cout << arg.val_string;
|
|
else
|
|
std::cout << arg.val_number;
|
|
}
|
|
else if(arg.type == TokenType::IDENTIFIER)
|
|
{
|
|
if(rt.resolve_var_type(arg.val_string) == ValueType::STRING)
|
|
std::cout << rt.resolve_var_str(arg.val_string);
|
|
else if (rt.resolve_var_type(arg.val_string) == ValueType::NUMBER)
|
|
std::cout << rt.resolve_var_num(arg.val_string);
|
|
}
|
|
}
|
|
std::cout << std::endl;
|
|
}
|
|
},
|
|
{
|
|
.name = "exit",
|
|
.expected_num_args = 0,
|
|
.func = [](Runtime& rt, const std::vector<Token>& tokens)
|
|
{
|
|
std::exit(EXIT_SUCCESS);
|
|
}
|
|
},
|
|
{
|
|
.name = "assign",
|
|
.expected_num_args = 2,
|
|
.expected_token_types = {TokenType::ID_OR_LIT, TokenType::IDENTIFIER},
|
|
.expected_value_types = {ValueType::ANY, ValueType::ANY},
|
|
.func = [](Runtime& rt, const std::vector<Token>& tokens)
|
|
{
|
|
if(tokens[0].type == TokenType::LITERAL)
|
|
{
|
|
if(tokens[0].value_type == ValueType::NUMBER)
|
|
rt.assign_var_num(tokens[1].val_string, tokens[0].val_number);
|
|
else
|
|
rt.assign_var_str(tokens[1].val_string, tokens[0].val_string);
|
|
}
|
|
else if(tokens[0].type == TokenType::IDENTIFIER)
|
|
{
|
|
if(rt.resolve_var_type(tokens[0].val_string) == ValueType::NUMBER)
|
|
rt.assign_var_num(tokens[1].val_string, rt.resolve_var_num(tokens[0].val_string));
|
|
else
|
|
rt.assign_var_str(tokens[1].val_string, rt.resolve_var_str(tokens[0].val_string));
|
|
}
|
|
}
|
|
},
|
|
{
|
|
.name = "add",
|
|
.expected_num_args = 3,
|
|
.expected_token_types = {TokenType::ID_OR_LIT, TokenType::ID_OR_LIT, TokenType::IDENTIFIER},
|
|
.expected_value_types = {ValueType::NUMBER, ValueType::NUMBER, ValueType::NUMBER},
|
|
.func = [](Runtime& rt, const std::vector<Token>& tokens)
|
|
{
|
|
float operands[2], res;
|
|
|
|
// Retrieve operands
|
|
for(unsigned int i = 0; i < 2; i++)
|
|
{
|
|
if(tokens[i].type == TokenType::LITERAL)
|
|
operands[i] = tokens[i].val_number;
|
|
else
|
|
operands[i] = rt.resolve_var_num(tokens[i].val_string);
|
|
}
|
|
|
|
res = operands[0] + operands[1];
|
|
|
|
rt.assign_var_num(tokens[2].val_string, res);
|
|
}
|
|
},
|
|
{
|
|
.name = "mul",
|
|
.expected_num_args = 3,
|
|
.expected_token_types = {TokenType::ID_OR_LIT, TokenType::ID_OR_LIT, TokenType::IDENTIFIER},
|
|
.expected_value_types = {ValueType::NUMBER, ValueType::NUMBER, ValueType::NUMBER},
|
|
.func = [](Runtime& rt, const std::vector<Token>& tokens)
|
|
{
|
|
float operands[2], res;
|
|
|
|
// Retrieve operands
|
|
for(unsigned int i = 0; i < 2; i++)
|
|
{
|
|
if(tokens[i].type == TokenType::LITERAL)
|
|
operands[i] = tokens[i].val_number;
|
|
else
|
|
operands[i] = rt.resolve_var_num(tokens[i].val_string);
|
|
}
|
|
|
|
res = operands[0] * operands[1];
|
|
|
|
rt.assign_var_num(tokens[2].val_string, res);
|
|
}
|
|
},
|
|
{
|
|
.name = "div",
|
|
.expected_num_args = 3,
|
|
.expected_token_types = {TokenType::ID_OR_LIT, TokenType::ID_OR_LIT, TokenType::IDENTIFIER},
|
|
.expected_value_types = {ValueType::NUMBER, ValueType::NUMBER, ValueType::NUMBER},
|
|
.func = [](Runtime& rt, const std::vector<Token>& tokens)
|
|
{
|
|
float operands[2], res;
|
|
|
|
// Retrieve operands
|
|
for(unsigned int i = 0; i < 2; i++)
|
|
{
|
|
if(tokens[i].type == TokenType::LITERAL)
|
|
operands[i] = tokens[i].val_number;
|
|
else
|
|
operands[i] = rt.resolve_var_num(tokens[i].val_string);
|
|
}
|
|
|
|
res = operands[0] / operands[1];
|
|
|
|
rt.assign_var_num(tokens[2].val_string, res);
|
|
}
|
|
},
|
|
{
|
|
.name = "sub",
|
|
.expected_num_args = 3,
|
|
.expected_token_types = {TokenType::ID_OR_LIT, TokenType::ID_OR_LIT, TokenType::IDENTIFIER},
|
|
.expected_value_types = {ValueType::NUMBER, ValueType::NUMBER, ValueType::NUMBER},
|
|
.func = [](Runtime& rt, const std::vector<Token>& tokens)
|
|
{
|
|
float operands[2], res;
|
|
|
|
// Retrieve operands
|
|
for(unsigned int i = 0; i < 2; i++)
|
|
{
|
|
if(tokens[i].type == TokenType::LITERAL)
|
|
operands[i] = tokens[i].val_number;
|
|
else
|
|
operands[i] = rt.resolve_var_num(tokens[i].val_string);
|
|
}
|
|
|
|
res = operands[0] - operands[1];
|
|
|
|
rt.assign_var_num(tokens[2].val_string, res);
|
|
}
|
|
},
|
|
{
|
|
.name = "goto",
|
|
.expected_num_args = 2,
|
|
.expected_token_types = {TokenType::ID_OR_LIT, TokenType::ID_OR_LIT},
|
|
.expected_value_types = {ValueType::NUMBER, ValueType::NUMBER},
|
|
.func = [](Runtime& rt, const std::vector<Token>& tokens)
|
|
{
|
|
int dest;
|
|
float condition;
|
|
|
|
if(tokens[0].type == TokenType::LITERAL)
|
|
dest = std::floor(tokens[0].val_number);
|
|
else
|
|
dest = std::floor(rt.resolve_var_num(tokens[0].val_string));
|
|
|
|
if(tokens[1].type == TokenType::LITERAL)
|
|
condition = std::floor(tokens[1].val_number);
|
|
else
|
|
condition = std::floor(rt.resolve_var_num(tokens[1].val_string));
|
|
|
|
if(condition > 0.0f)
|
|
rt.jump_instructions(dest);
|
|
}
|
|
},
|
|
{
|
|
.name = "jump",
|
|
.expected_num_args = 2,
|
|
.expected_token_types = {TokenType::ID_OR_LIT, TokenType::ID_OR_LIT},
|
|
.expected_value_types = {ValueType::NUMBER, ValueType::NUMBER},
|
|
.func = [](Runtime& rt, const std::vector<Token>& tokens)
|
|
{
|
|
int offset, dest;
|
|
float condition;
|
|
|
|
if(tokens[0].type == TokenType::LITERAL)
|
|
offset = std::floor(tokens[0].val_number);
|
|
else
|
|
offset = std::floor(rt.resolve_var_num(tokens[0].val_string));
|
|
|
|
if(tokens[1].type == TokenType::LITERAL)
|
|
condition = std::floor(tokens[1].val_number);
|
|
else
|
|
condition = std::floor(rt.resolve_var_num(tokens[1].val_string));
|
|
|
|
dest = rt.instruction_counter + dest;
|
|
|
|
if(condition > 0.0f)
|
|
rt.jump_instructions(dest);
|
|
}
|
|
},
|
|
{
|
|
.name = "strin",
|
|
.expected_num_args = 2,
|
|
.expected_token_types = {TokenType::ID_OR_LIT, TokenType::IDENTIFIER},
|
|
.expected_value_types = {ValueType::STRING, ValueType::ANY},
|
|
.func = [](Runtime& rt, const std::vector<Token>& tokens)
|
|
{
|
|
if(tokens[0].type == TokenType::LITERAL)
|
|
std::cout << tokens[0].val_string << " ";
|
|
else
|
|
std::cout << rt.resolve_var_str(tokens[0].val_string) << " ";
|
|
|
|
std::string str;
|
|
std::cin >> str;
|
|
|
|
rt.assign_var_str(tokens[1].val_string, str);
|
|
}
|
|
},
|
|
{
|
|
.name = "numin",
|
|
.expected_num_args = 2,
|
|
.expected_token_types = {TokenType::ID_OR_LIT, TokenType::IDENTIFIER},
|
|
.expected_value_types = {ValueType::STRING, ValueType::ANY},
|
|
.func = [](Runtime& rt, const std::vector<Token>& tokens)
|
|
{
|
|
if(tokens[0].type == TokenType::LITERAL)
|
|
std::cout << tokens[0].val_string << " ";
|
|
else
|
|
std::cout << rt.resolve_var_str(tokens[0].val_string) << " ";
|
|
|
|
float num;
|
|
std::cin >> num;
|
|
|
|
rt.assign_var_num(tokens[1].val_string, num);
|
|
}
|
|
},
|
|
{
|
|
.name = "rand",
|
|
.expected_num_args = 2,
|
|
.expected_token_types = {TokenType::ID_OR_LIT, TokenType::IDENTIFIER},
|
|
.expected_value_types = {ValueType::NUMBER, ValueType::ANY},
|
|
.func = [](Runtime& rt, const std::vector<Token>& tokens)
|
|
{
|
|
int limit;
|
|
if(tokens[0].type == TokenType::LITERAL)
|
|
limit = tokens[0].val_number;
|
|
else
|
|
limit = rt.resolve_var_num(tokens[0].val_string);
|
|
|
|
int number = rand() % limit;
|
|
|
|
rt.assign_var_num(tokens[1].val_string, number);
|
|
}
|
|
},
|
|
{
|
|
.name = "equal",
|
|
.expected_num_args = 3,
|
|
.expected_token_types = {TokenType::ID_OR_LIT, TokenType::ID_OR_LIT, TokenType::IDENTIFIER},
|
|
.expected_value_types = {ValueType::NUMBER, ValueType::NUMBER, ValueType::NUMBER},
|
|
.func = [](Runtime& rt, const std::vector<Token>& tokens)
|
|
{
|
|
float operands[2], res;
|
|
|
|
// Retrieve operands
|
|
for(unsigned int i = 0; i < 2; i++)
|
|
{
|
|
if(tokens[i].type == TokenType::LITERAL)
|
|
operands[i] = tokens[i].val_number;
|
|
else
|
|
operands[i] = rt.resolve_var_num(tokens[i].val_string);
|
|
}
|
|
|
|
res = std::round(operands[0]) == std::round(operands[1]);
|
|
|
|
rt.assign_var_num(tokens[2].val_string, res);
|
|
}
|
|
}
|
|
};
|