15 if (operand.size() != 1) {
21 int64_t result = std::abs(value);
24 program->
vars[
"%rax"].var_value.int_value = result;
28 if (operand.size() != 1) {
39 double result = std::fabs(value);
42 program->
vars[
"%rax"].var_value.float_value = result;
46 if (operand.size() != 1) {
57 double result = std::sqrt(value);
60 program->
vars[
"%rax"].var_value.float_value = result;
64 if (operand.size() != 2) {
65 throw mx::Exception(
"pow requires 2 arguments (base, exponent).");
68 double base, exponent;
74 base =
static_cast<double>(operand[0].op_value);
81 exponent =
static_cast<double>(operand[1].op_value);
84 double result = std::pow(base, exponent);
87 program->
vars[
"%rax"].var_value.float_value = result;
91 if (operand.size() != 1) {
102 double result = std::sin(value);
105 program->
vars[
"%rax"].var_value.float_value = result;
109 if (operand.size() != 1) {
120 double result = std::cos(value);
123 program->
vars[
"%rax"].var_value.float_value = result;
127 if (operand.size() != 1) {
138 double result = std::tan(value);
141 program->
vars[
"%rax"].var_value.float_value = result;
145 if (operand.size() != 1) {
156 double result = std::floor(value);
159 program->
vars[
"%rax"].var_value.float_value = result;
163 if (operand.size() != 1) {
174 double result = std::ceil(value);
177 program->
vars[
"%rax"].var_value.float_value = result;
182 int64_t result = std::rand();
185 program->
vars[
"%rax"].var_value.int_value = result;
189 if (operand.size() != 1) {
195 std::srand(
static_cast<unsigned int>(seed));
200 if (operand.size() != 1) {
206 void *result = std::malloc(
static_cast<size_t>(size));
207 if (result ==
nullptr) {
208 throw mx::Exception(
"malloc failed to allocate " + std::to_string(size) +
" bytes");
212 program->
vars[
"%rax"].var_value.ptr_value = result;
213 program->
vars[
"%rax"].var_value.owns =
true;
214 program->
vars[
"%rax"].var_value.ptr_size =
static_cast<uint64_t
>(size);
215 program->
vars[
"%rax"].var_value.ptr_count = 1;
219 if (operand.size() != 2) {
220 throw mx::Exception(
"calloc requires 2 arguments (count, size).");
226 void *result = std::calloc(
static_cast<size_t>(count),
static_cast<size_t>(size));
227 if (result ==
nullptr) {
228 throw mx::Exception(
"calloc failed to allocate " + std::to_string(count) +
" * " + std::to_string(size) +
" bytes");
232 program->
vars[
"%rax"].var_value.ptr_value = result;
233 program->
vars[
"%rax"].var_value.owns =
true;
234 program->
vars[
"%rax"].var_value.ptr_size =
static_cast<uint64_t
>(size);
235 program->
vars[
"%rax"].var_value.ptr_count =
static_cast<uint64_t
>(count);
239 if (operand.size() != 1) {
249 throw mx::Exception(
"free argument must be a pointer variable.");
261 if (operand.size() != 1) {
262 throw mx::Exception(
"toupper requires 1 argument (character).");
267 int64_t result = std::toupper(
static_cast<int>(ch));
270 program->
vars[
"%rax"].var_value.int_value = result;
274 if (operand.size() != 1) {
275 throw mx::Exception(
"tolower requires 1 argument (character).");
280 int64_t result = std::tolower(
static_cast<int>(ch));
283 program->
vars[
"%rax"].var_value.int_value = result;
287 if (operand.size() != 1) {
288 throw mx::Exception(
"isalpha requires 1 argument (character).");
293 int64_t result = std::isalpha(
static_cast<int>(ch)) ? 1 : 0;
296 program->
vars[
"%rax"].var_value.int_value = result;
300 if (operand.size() != 1) {
301 throw mx::Exception(
"isdigit requires 1 argument (character).");
306 int64_t result = std::isdigit(
static_cast<int>(ch)) ? 1 : 0;
309 program->
vars[
"%rax"].var_value.int_value = result;
313 if (operand.size() != 1) {
314 throw mx::Exception(
"isspace requires 1 argument (character).");
319 int64_t result = std::isspace(
static_cast<int>(ch)) ? 1 : 0;
322 program->
vars[
"%rax"].var_value.int_value = result;
327 if (operand.size() != 1) {
336 const char *str =
nullptr;
346 throw mx::Exception(
"atoi argument must be a string or pointer variable.");
349 int64_t result = std::atoi(str);
352 program->
vars[
"%rax"].var_value.int_value = result;
356 if (operand.size() != 1) {
365 const char *str =
nullptr;
375 throw mx::Exception(
"atof argument must be a string or pointer variable.");
378 double result = std::atof(str);
381 program->
vars[
"%rax"].var_value.float_value = result;
386 int64_t exit_code = 0;
387 if (!operand.empty()) {
391 std::exit(
static_cast<int>(exit_code));
395 if (operand.size() != 1) {
396 throw mx::Exception(
"system requires 1 argument (command).");
404 const char *command =
nullptr;
414 throw mx::Exception(
"system argument must be a string or pointer variable.");
417 int64_t result = std::system(command);
420 program->
vars[
"%rax"].var_value.int_value = result;
426 if (operand.size() != 3) {
427 throw mx::Exception(
"memcpy requires 3 arguments (dest, src, size).");
431 throw mx::Exception(
"memcpy dest and src must be pointer variables.");
438 throw mx::Exception(
"memcpy dest and src must be pointer variables.");
449 n =
static_cast<size_t>(operand[2].op_value);
463 if (operand.size() != 3) {
464 throw mx::Exception(
"memcmp requires 3 arguments (ptr1, ptr2, size).");
468 throw mx::Exception(
"memcmp ptr1 and ptr2 must be pointer variables.");
475 throw mx::Exception(
"memcmp ptr1 and ptr2 must be pointer variables.");
486 n =
static_cast<size_t>(operand[2].op_value);
496 program->
vars[
"%rax"].var_value.int_value =
static_cast<int64_t
>(result);
500 if (operand.size() != 3) {
501 throw mx::Exception(
"memmove requires 3 arguments (dest, src, size).");
505 throw mx::Exception(
"memmove dest and src must be pointer variables.");
512 throw mx::Exception(
"memmove dest and src must be pointer variables.");
523 n =
static_cast<size_t>(operand[2].op_value);
537 if (operand.size() != 3) {
538 throw mx::Exception(
"memset requires 3 arguments (dest, value, size).");
542 throw mx::Exception(
"memset dest must be a pointer variable.");
548 throw mx::Exception(
"memset dest must be a pointer variable.");
558 value =
static_cast<int>(operand[1].op_value);
566 n =
static_cast<size_t>(operand[2].op_value);
579 if (operand.size() != 1)
582 : (double)operand[0].op_value;
583 double r = std::exp(v);
586 program->
vars[
"%rax"].var_value.float_value = r;
590 if (operand.size() != 1)
593 : (double)operand[0].op_value;
594 double r = std::exp2(v);
597 program->
vars[
"%rax"].var_value.float_value = r;
601 if (operand.size() != 1)
604 : (double)operand[0].op_value;
605 double r = std::log(v);
608 program->
vars[
"%rax"].var_value.float_value = r;
612 if (operand.size() != 1)
615 : (double)operand[0].op_value;
616 double r = std::log10(v);
619 program->
vars[
"%rax"].var_value.float_value = r;
623 if (operand.size() != 1)
626 : (double)operand[0].op_value;
627 double r = std::log2(v);
630 program->
vars[
"%rax"].var_value.float_value = r;
634 if (operand.size() != 2)
637 : (double)operand[0].op_value;
639 : (double)operand[1].op_value;
640 double r = std::fmod(x, y);
643 program->
vars[
"%rax"].var_value.float_value = r;
647 if (operand.size() != 2)
650 : (double)operand[0].op_value;
652 : (double)operand[1].op_value;
653 double r = std::atan2(y, x);
656 program->
vars[
"%rax"].var_value.float_value = r;
660 if (operand.size() != 1)
663 : (double)operand[0].op_value;
664 double r = std::asin(v);
667 program->
vars[
"%rax"].var_value.float_value = r;
671 if (operand.size() != 1)
674 : (double)operand[0].op_value;
675 double r = std::acos(v);
678 program->
vars[
"%rax"].var_value.float_value = r;
682 if (operand.size() != 1)
685 : (double)operand[0].op_value;
686 double r = std::atan(v);
689 program->
vars[
"%rax"].var_value.float_value = r;
693 if (operand.size() != 1)
696 : (double)operand[0].op_value;
697 double r = std::sinh(v);
700 program->
vars[
"%rax"].var_value.float_value = r;
704 if (operand.size() != 1)
707 : (double)operand[0].op_value;
708 double r = std::cosh(v);
711 program->
vars[
"%rax"].var_value.float_value = r;
715 if (operand.size() != 1)
718 : (double)operand[0].op_value;
719 double r = std::tanh(v);
722 program->
vars[
"%rax"].var_value.float_value = r;
726 if (operand.size() != 2)
729 : (double)operand[0].op_value;
731 : (double)operand[1].op_value;
732 double r = std::hypot(x, y);
735 program->
vars[
"%rax"].var_value.float_value = r;
739 if (operand.size() != 1)
742 : (double)operand[0].op_value;
743 double r = std::round(v);
746 program->
vars[
"%rax"].var_value.float_value = r;
750 if (operand.size() != 1)
753 : (double)operand[0].op_value;
754 double r = std::trunc(v);
757 program->
vars[
"%rax"].var_value.float_value = r;
765 program->
vars[
"%rax"].var_value.int_value = (int64_t)v;
769 if (operand.size() != 1) {
775 idx = (int)operand[0].op_value;
776 }
else if (program->
isVariable(operand[0].op)) {
783 throw mx::Exception(
"argv argument must be an index constant or integer variable");
786 const char *s =
argv(idx);
789 program->
vars[
"%rax"].var_value.ptr_value = (
void *)s;
797 if (operand.size() != 2) {
798 throw mx::Exception(
"set_program_args requires 2 arguments (argc, argv)");
802 throw mx::Exception(
"set_program_args arguments must be variables");
809 throw mx::Exception(
"set_program_args first argument (argc) must be an integer");
813 throw mx::Exception(
"set_program_args second argument (argv) must be a pointer");
820 throw mx::Exception(
"set_program_args: argv pointer is null but argc > 0");
827 if (operand.size() != 1) {
828 throw mx::Exception(
"float_to_int requires 1 argument (float value).");
839 throw mx::Exception(
"float_to_int argument must be a float or integer variable.");
842 value =
static_cast<double>(operand[0].op_value);
845 int64_t result =
static_cast<int64_t
>(value);
848 program->
vars[
"%rax"].var_value.int_value = result;
852 if (operand.size() != 1) {
853 throw mx::Exception(
"int_to_float requires 1 argument (integer value).");
864 throw mx::Exception(
"int_to_float argument must be an integer or float variable.");
867 value = operand[0].op_value;
870 double result =
static_cast<double>(value);
873 program->
vars[
"%rax"].var_value.float_value = result;
General-purpose exception with errno-aware factory method.
std::unordered_map< std::string, Variable > vars
variable symbol table
Complete MXVM program: instruction interpreter and native x64 code generator.
Variable & getVariable(const std::string &name)
Look up a variable by name, searching local scope then global.
bool isVariable(const std::string &name)
Check whether a variable exists in local or global scope.
Intermediate code representation, execution engine, and native x64 code generation (SysV + Win64).
Standard library module C API — function declarations exported to MXVM programs.
void free_program_args(void)
Free the stored command-line argument memory.
void set_program_args(int argc, const char **argv)
Store command-line arguments for later access via argc()/argv().
int argc(void)
Return the number of stored command-line arguments.
const char * argv(int idx)
Return the command-line argument at the given index.
void except_assert(std::string reason, bool value)
Assert a condition, throwing an Exception with the given reason on failure.
void mxvm_std_release(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_rand(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_log(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_malloc(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_fmod(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_tanh(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_free_program_args(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_exit(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_sin(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_float_to_int(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_cosh(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_exp2(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_isspace(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_memcpy(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_srand(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_set_program_args(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_argc(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_abs(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_trunc(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_system(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_round(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_isalpha(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_floor(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_calloc(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_memmove(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_atan(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_atof(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_sinh(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_tan(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_exp(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_int_to_float(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_tolower(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_atoi(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_isdigit(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_cos(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_sqrt(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_log10(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_acos(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_asin(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_toupper(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_memcmp(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_pow(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_hypot(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_log2(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_argv(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_atan2(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_ceil(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_fabs(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
void mxvm_std_memset(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
uint64_t ptr_size
size of each element in allocated memory
bool owns
true if this value owns the allocated memory
uint64_t ptr_count
number of elements allocated
A named variable with type, value, and optional object association.