add multiplication, division, and &&

This commit is contained in:
William Bell
2025-09-03 05:21:41 +01:00
parent df040adf45
commit 57728af0b6
10 changed files with 286 additions and 31 deletions

View File

@@ -6,6 +6,7 @@
#include "call.h"
#include "../../hash_data/hash_data.h"
#include "../objects/literals/literals.h"
#include "../objects/string/string.h"
#include <inttypes.h>
#include <math.h>
@@ -143,7 +144,8 @@ void run_call(ArgonObject *original_object, size_t argc, ArgonObject **argv,
object->value.argon_fn.bytecode_length, false},
object->value.argon_fn.translated.constants,
object->value.argon_fn.translated.path},
{ar_alloc(object->value.argon_fn.translated.registerCount * sizeof(ArgonObject *)),
{ar_alloc(object->value.argon_fn.translated.registerCount *
sizeof(ArgonObject *)),
0,
object->value.argon_fn.translated.path,
NULL,
@@ -153,6 +155,9 @@ void run_call(ArgonObject *original_object, size_t argc, ArgonObject **argv,
scope,
*state->currentStackFramePointer,
(*state->currentStackFramePointer)->depth + 1};
for (size_t i = 0; i < new_stackFrame.translated.registerCount; i++) {
new_stackFrame.state.registers[i] = ARGON_NULL;
}
if (CStackFrame) {
runtime(new_stackFrame.translated, new_stackFrame.state,
new_stackFrame.stack, err);

View File

@@ -147,8 +147,6 @@ ArgonObject *ARGON_NUMBER_TYPE___subtract__(size_t argc, ArgonObject **argv,
"__subtract__ expects 2 arguments, got %" PRIu64, argc);
return ARGON_NULL;
}
mpq_t r;
mpq_init(r);
if (argv[1]->type != TYPE_NUMBER) {
ArgonObject *type_name = get_builtin_field_for_class(
get_builtin_field(argv[1], __class__, false, false), __name__, argv[1]);
@@ -158,6 +156,7 @@ ArgonObject *ARGON_NUMBER_TYPE___subtract__(size_t argc, ArgonObject **argv,
type_name->value.as_str.length, type_name->value.as_str.data);
return ARGON_NULL;
}
if (argv[0]->value.as_number.is_int64 && argv[1]->value.as_number.is_int64) {
int64_t a = argv[0]->value.as_number.n.i64;
int64_t b = argv[1]->value.as_number.n.i64;
@@ -213,8 +212,6 @@ ArgonObject *ARGON_NUMBER_TYPE___multiply__(size_t argc, ArgonObject **argv,
"__multiply__ expects 2 arguments, got %" PRIu64, argc);
return ARGON_NULL;
}
mpq_t r;
mpq_init(r);
if (argv[1]->type != TYPE_NUMBER) {
ArgonObject *type_name = get_builtin_field_for_class(
get_builtin_field(argv[1], __class__, false, false), __name__, argv[1]);
@@ -224,10 +221,52 @@ ArgonObject *ARGON_NUMBER_TYPE___multiply__(size_t argc, ArgonObject **argv,
type_name->value.as_str.length, type_name->value.as_str.data);
return ARGON_NULL;
}
mpq_mul(r, *argv[0]->value.as_number.n.mpq, *argv[1]->value.as_number.n.mpq);
ArgonObject *result = new_number_object(r);
mpq_clear(r);
return result;
if (argv[0]->value.as_number.is_int64 && argv[1]->value.as_number.is_int64) {
int64_t a = argv[0]->value.as_number.n.i64;
int64_t b = argv[1]->value.as_number.n.i64;
bool gonna_overflow =
a > 0 ? (b > 0 ? a > INT64_MAX / b : b < INT64_MIN / a)
: (b > 0 ? a < INT64_MIN / b : a != 0 && b < INT64_MAX / a);
if (!gonna_overflow) {
return new_number_object_from_int64(a * b);
}
mpq_t a_GMP, b_GMP;
mpq_init(a_GMP);
mpq_init(b_GMP);
mpq_set_si(a_GMP, a, 1);
mpq_set_si(b_GMP, b, 1);
mpq_mul(a_GMP, a_GMP, b_GMP);
ArgonObject *result = new_number_object(a_GMP);
mpq_clear(a_GMP);
mpq_clear(b_GMP);
return result;
} else if (!argv[0]->value.as_number.is_int64 &&
!argv[1]->value.as_number.is_int64) {
mpq_t r;
mpq_init(r);
mpq_mul(r, *argv[0]->value.as_number.n.mpq,
*argv[1]->value.as_number.n.mpq);
ArgonObject *result = new_number_object(r);
mpq_clear(r);
return result;
} else {
mpq_t a_GMP, b_GMP;
mpq_init(a_GMP);
mpq_init(b_GMP);
if (argv[0]->value.as_number.is_int64) {
mpq_set_si(a_GMP, argv[0]->value.as_number.n.i64, 1);
mpq_set(b_GMP, *argv[1]->value.as_number.n.mpq);
} else {
mpq_set(a_GMP, *argv[0]->value.as_number.n.mpq);
mpq_set_si(b_GMP, argv[1]->value.as_number.n.i64, 1);
}
mpq_mul(a_GMP, a_GMP, b_GMP);
ArgonObject *result = new_number_object(a_GMP);
mpq_clear(a_GMP);
mpq_clear(b_GMP);
return result;
}
}
ArgonObject *ARGON_NUMBER_TYPE___division__(size_t argc, ArgonObject **argv,
@@ -238,8 +277,6 @@ ArgonObject *ARGON_NUMBER_TYPE___division__(size_t argc, ArgonObject **argv,
"__division__ expects 2 arguments, got %" PRIu64, argc);
return ARGON_NULL;
}
mpq_t r;
mpq_init(r);
if (argv[1]->type != TYPE_NUMBER) {
ArgonObject *type_name = get_builtin_field_for_class(
get_builtin_field(argv[1], __class__, false, false), __name__, argv[1]);
@@ -249,10 +286,36 @@ ArgonObject *ARGON_NUMBER_TYPE___division__(size_t argc, ArgonObject **argv,
type_name->value.as_str.length, type_name->value.as_str.data);
return ARGON_NULL;
}
mpq_div(r, *argv[0]->value.as_number.n.mpq, *argv[1]->value.as_number.n.mpq);
ArgonObject *result = new_number_object(r);
mpq_clear(r);
return result;
if (argv[0]->value.as_number.is_int64 && argv[1]->value.as_number.is_int64) {
int64_t a = argv[0]->value.as_number.n.i64;
int64_t b = argv[1]->value.as_number.n.i64;
return new_number_object_from_num_and_den(a, b);
} else if (!argv[0]->value.as_number.is_int64 &&
!argv[1]->value.as_number.is_int64) {
mpq_t r;
mpq_init(r);
mpq_div(r, *argv[0]->value.as_number.n.mpq,
*argv[1]->value.as_number.n.mpq);
ArgonObject *result = new_number_object(r);
mpq_clear(r);
return result;
} else {
mpq_t a_GMP, b_GMP;
mpq_init(a_GMP);
mpq_init(b_GMP);
if (argv[0]->value.as_number.is_int64) {
mpq_set_si(a_GMP, argv[0]->value.as_number.n.i64, 1);
mpq_set(b_GMP, *argv[1]->value.as_number.n.mpq);
} else {
mpq_set(a_GMP, *argv[0]->value.as_number.n.mpq);
mpq_set_si(b_GMP, argv[1]->value.as_number.n.i64, 1);
}
mpq_div(a_GMP, a_GMP, b_GMP);
ArgonObject *result = new_number_object(a_GMP);
mpq_clear(a_GMP);
mpq_clear(b_GMP);
return result;
}
}
ArgonObject *ARGON_NUMBER_TYPE___string__(size_t argc, ArgonObject **argv,

View File

@@ -681,6 +681,9 @@ RuntimeState init_runtime_state(Translated translated, char *path) {
NULL,
{0, 0, 0},
{}};
for (size_t i = 0;i<translated.registerCount;i++) {
runtime.registers[i] = ARGON_NULL;
}
return runtime;
}
@@ -715,7 +718,9 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack,
[OP_COPY_TO_REGISTER] = &&DO_COPY_TO_REGISTER,
[OP_ADDITION] = &&DO_ADDITION,
[OP_SUBTRACTION] = &&DO_SUBTRACTION,
[OP_LOAD_ACCESS_FUNCTION] = &&DO_LOAD_ACCESS_FUNCTION};
[OP_LOAD_ACCESS_FUNCTION] = &&DO_LOAD_ACCESS_FUNCTION,
[OP_MULTIPLICATION] = &&DO_MULTIPLICATION,
[OP_DIVISION] = &&DO_DIVISION};
_state.head = 0;
StackFrame *currentStackFrame = ar_alloc(sizeof(StackFrame));
@@ -752,9 +757,9 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack,
continue;
DO_BOOL: {
uint8_t to_register = pop_byte(translated, state);
if (likely(state->registers[0]->type != TYPE_OBJECT)) {
if (likely(state->registers[to_register]->type != TYPE_OBJECT)) {
state->registers[to_register] =
state->registers[0]->as_bool ? ARGON_TRUE : ARGON_FALSE;
state->registers[to_register]->as_bool ? ARGON_TRUE : ARGON_FALSE;
continue;
}
ArgonObject *args[] = {ARGON_BOOL_TYPE, state->registers[0]};
@@ -937,13 +942,122 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack,
ArgonObject *args[] = {valueA, valueB};
state->registers[registerC] =
ARGON_ADDITION_FUNCTION(2, args, err, state);
ARGON_SUBTRACTION_FUNCTION(2, args, err, state);
continue;
}
DO_MULTIPLICATION: {
uint8_t registerA = pop_byte(translated, state);
uint8_t registerB = pop_byte(translated, state);
uint8_t registerC = pop_byte(translated, state);
ArgonObject *valueA = state->registers[registerA];
ArgonObject *valueB = state->registers[registerB];
if (likely(valueA->type == TYPE_NUMBER && valueB->type == TYPE_NUMBER)) {
if (likely(valueA->value.as_number.is_int64 &&
valueB->value.as_number.is_int64)) {
int64_t a = valueA->value.as_number.n.i64;
int64_t b = valueB->value.as_number.n.i64;
bool gonna_overflow =
a > 0 ? (b > 0 ? a > INT64_MAX / b : b < INT64_MIN / a)
: (b > 0 ? a < INT64_MIN / b : a != 0 && b < INT64_MAX / a);
if (!gonna_overflow) {
state->registers[registerC] = new_number_object_from_int64(a * b);
continue;
}
mpq_t a_GMP, b_GMP;
mpq_init(a_GMP);
mpq_init(b_GMP);
mpq_set_si(a_GMP, a, 1);
mpq_set_si(b_GMP, b, 1);
mpq_mul(a_GMP, a_GMP, b_GMP);
state->registers[registerC] = new_number_object(a_GMP);
mpq_clear(a_GMP);
mpq_clear(b_GMP);
} else if (!valueA->value.as_number.is_int64 &&
!valueB->value.as_number.is_int64) {
mpq_t r;
mpq_init(r);
mpq_mul(r, *valueA->value.as_number.n.mpq,
*valueB->value.as_number.n.mpq);
state->registers[registerC] = new_number_object(r);
mpq_clear(r);
} else {
mpq_t a_GMP, b_GMP;
mpq_init(a_GMP);
mpq_init(b_GMP);
if (valueA->value.as_number.is_int64) {
mpq_set_si(a_GMP, valueA->value.as_number.n.i64, 1);
mpq_set(b_GMP, *valueB->value.as_number.n.mpq);
} else {
mpq_set(a_GMP, *valueA->value.as_number.n.mpq);
mpq_set_si(b_GMP, valueB->value.as_number.n.i64, 1);
}
mpq_mul(a_GMP, a_GMP, b_GMP);
state->registers[registerC] = new_number_object(a_GMP);
mpq_clear(a_GMP);
mpq_clear(b_GMP);
}
continue;
}
ArgonObject *args[] = {valueA, valueB};
state->registers[registerC] =
ARGON_MULTIPLY_FUNCTION(2, args, err, state);
continue;
}
DO_DIVISION: {
uint8_t registerA = pop_byte(translated, state);
uint8_t registerB = pop_byte(translated, state);
uint8_t registerC = pop_byte(translated, state);
ArgonObject *valueA = state->registers[registerA];
ArgonObject *valueB = state->registers[registerB];
if (likely(valueA->type == TYPE_NUMBER && valueB->type == TYPE_NUMBER)) {
if (likely(valueA->value.as_number.is_int64 &&
valueB->value.as_number.is_int64)) {
int64_t a = valueA->value.as_number.n.i64;
int64_t b = valueB->value.as_number.n.i64;
state->registers[registerC] =
new_number_object_from_num_and_den(a, b);
} else if (!valueA->value.as_number.is_int64 &&
!valueB->value.as_number.is_int64) {
mpq_t r;
mpq_init(r);
mpq_div(r, *valueA->value.as_number.n.mpq,
*valueB->value.as_number.n.mpq);
state->registers[registerC] = new_number_object(r);
mpq_clear(r);
} else {
mpq_t a_GMP, b_GMP;
mpq_init(a_GMP);
mpq_init(b_GMP);
if (valueA->value.as_number.is_int64) {
mpq_set_si(a_GMP, valueA->value.as_number.n.i64, 1);
mpq_set(b_GMP, *valueB->value.as_number.n.mpq);
} else {
mpq_set(a_GMP, *valueA->value.as_number.n.mpq);
mpq_set_si(b_GMP, valueB->value.as_number.n.i64, 1);
}
mpq_div(a_GMP, a_GMP, b_GMP);
state->registers[registerC] = new_number_object(a_GMP);
mpq_clear(a_GMP);
mpq_clear(b_GMP);
}
continue;
}
ArgonObject *args[] = {valueA, valueB};
state->registers[registerC] =
ARGON_DIVISION_FUNCTION(2, args, err, state);
continue;
}
}
ArgonObject *result = currentStackFrame->state.registers[0];
currentStackFrame = currentStackFrame->previousStackFrame;
if(currentStackFrame) currentStackFrame->state.registers[0] = result;
if (currentStackFrame)
currentStackFrame->state.registers[0] = result;
}
}