var Int_Eq(var self, var other) { IntData* io = cast(self, Int); if (type_implements(type_of(other), AsLong)) { return (var)(intptr_t)(io->value == as_long(other)); } else { return False; } }
friend closure_value operator! (closure_value const &rhs) { switch (rhs.type) { case is_int: return closure_value(!as_long(rhs), rhs.valid); case is_bool: return closure_value(!as_bool(rhs), rhs.valid); case is_uint: break; } return closure_value(!as_ulong(rhs), rhs.valid); }
friend closure_value operator- (closure_value const &rhs) { switch (rhs.type) { case is_int: { long value = as_long(rhs); if (value != 0 && value == -value) return closure_value(-value, error_integer_overflow); return closure_value(-value, rhs.valid); } case is_bool: return closure_value(-as_long(rhs), rhs.valid); case is_uint: break; } long value = as_ulong(rhs); if (value != 0 && value == -value) return closure_value(-value, error_integer_overflow); return closure_value(-value, rhs.valid); }
friend closure_value operator< (closure_value const &lhs, closure_value const &rhs) { bool cmp = false; switch (lhs.type) { case is_int: switch(rhs.type) { case is_bool: cmp = lhs.value.i < as_long(rhs); break; case is_int: cmp = lhs.value.i < rhs.value.i; break; case is_uint: cmp = lhs.value.ui < rhs.value.ui; break; } break; case is_uint: cmp = lhs.value.ui < as_ulong(rhs); break; case is_bool: cmp = as_bool(lhs) < as_bool(rhs); break; } return closure_value(cmp, (value_error)(lhs.valid | rhs.valid)); }
closure_value &operator%= (closure_value const &rhs) { switch (type) { case is_int: switch(rhs.type) { case is_bool: case is_int: if (as_long(rhs) != 0) { if (value.i == -value.i && -1 == rhs.value.i) { // LONG_MIN % -1 on two's complement valid = error_integer_overflow; } else { value.i %= as_long(rhs); } } else { valid = error_division_by_zero; // division by zero } break; case is_uint: if (rhs.value.ui != 0) { value.ui %= rhs.value.ui; type = is_uint; } else { valid = error_division_by_zero; // division by zero } break; } break; case is_uint: if (as_ulong(rhs) != 0) value.ui %= as_ulong(rhs); else valid = error_division_by_zero; // division by zero break; case is_bool: if (as_bool(rhs)) { switch(rhs.type) { case is_int: value.i = (value.b ? 1 : 0) % rhs.value.i; type = is_int; break; case is_uint: value.i = (value.b ? 1 : 0) % rhs.value.ui; type = is_int; break; case is_bool: break; } } else { valid = error_division_by_zero; // division by zero } } return *this; }
closure_value &operator*= (closure_value const &rhs) { switch (type) { case is_int: switch(rhs.type) { case is_bool: value.i *= as_long(rhs); break; case is_int: { long result = value.i * rhs.value.i; if (0 != value.i && 0 != rhs.value.i && (result / value.i != rhs.value.i || result / rhs.value.i != value.i) ) { valid = error_integer_overflow; } else { value.i = result; } } break; case is_uint: { unsigned long result = value.ui * rhs.value.ui; if (0 != value.ui && 0 != rhs.value.ui && (result / value.ui != rhs.value.ui || result / rhs.value.ui != value.ui) ) { valid = error_integer_overflow; } else { value.ui = result; type = is_uint; } } break; } break; case is_uint: { unsigned long rhs_val = as_ulong(rhs); unsigned long result = value.ui * rhs_val; if (0 != value.ui && 0 != rhs_val && (result / value.ui != rhs_val || result / rhs_val != value.ui) ) { valid = error_integer_overflow; } else { value.ui = result; type = is_uint; } } break; case is_bool: switch (rhs.type) { case is_int: value.i = (value.b ? 1 : 0) * rhs.value.i; type = is_int; break; case is_uint: value.ui = (value.b ? 1 : 0) * rhs.value.ui; type = is_uint; break; case is_bool: value.b = 0 != ((value.b ? 1 : 0) * (rhs.value.b ? 1 : 0)); break; } } valid = (value_error)(valid | rhs.valid); return *this; }
closure_value &operator-= (closure_value const &rhs) { switch (type) { case is_int: switch(rhs.type) { case is_bool: { long result = value.i - as_long(rhs); if (rhs.value.i > 0L && result > value.i || rhs.value.i < 0L && result < value.i) { valid = error_integer_overflow; } else { value.i = result; } } break; case is_int: { long result = value.i - rhs.value.i; if (rhs.value.i > 0L && result > value.i || rhs.value.i < 0L && result < value.i) { valid = error_integer_overflow; } else { value.i = result; } } break; case is_uint: { unsigned long result = value.ui - rhs.value.ui; if (result > value.ui) { valid = error_integer_overflow; } else { value.ui = result; type = is_uint; } } break; } break; case is_uint: switch(rhs.type) { case is_bool: { unsigned long result = value.ui - as_ulong(rhs); if (result > value.ui) { valid = error_integer_overflow; } else { value.ui = result; } } break; case is_int: { unsigned long result = value.ui - rhs.value.i; if (rhs.value.i > 0L && result > value.ui || rhs.value.i < 0L && result < value.ui) { valid = error_integer_overflow; } else { value.ui = result; } } break; case is_uint: { unsigned long result = value.ui - rhs.value.ui; if (result > value.ui) { valid = error_integer_overflow; } else { value.ui = result; } } break; } break; case is_bool: value.i = value.b - as_bool(rhs); type = is_int; } valid = (value_error)(valid | rhs.valid); return *this; }
local var TestType_New(var self, var_list vl) { TestTypeData *ttd = cast(self, TestType); ttd->test_data = as_long(var_list_get(vl)); return self; }
x = cast(x, Int); y = cast(y, Real); PT_ASSERT(x); PT_ASSERT(y); } PT_FUNC(test_new) { var x = new(Int, $(Int, 1)); PT_ASSERT(x); PT_ASSERT(type_of(x) is Int); PT_ASSERT(as_long(x) is 1); delete(x); var y = $(Real, 0.0); construct(y, $(Real, 1.0)); PT_ASSERT(as_double(y) is 1.0); var z = allocate(String); PT_ASSERT(z); construct(z, $(String, "Hello")); PT_ASSERT_STR_EQ(as_str(z), "Hello"); z = destruct(z); deallocate(z); }
int print_to_va(var out, int pos, const char* fmt, va_list va) { char fmt_buf[strlen(fmt)+1]; while(true) { if (*fmt == '\0') { break; } const char* start = fmt; /* Match String */ while(!strchr("%\0", *fmt)) { fmt++; } if (start != fmt) { strncpy(fmt_buf, start, (fmt - start)); fmt_buf[(fmt - start)] = '\0'; int off = format_to(out, pos, fmt_buf); if (off < 0) { throw(FormatError, "Unable to output format!"); } pos += off; continue; } /* Match %% */ if (*fmt == '%' && *(fmt+1) == '%') { int off = format_to(out, pos, "%%"); if (off < 0) { throw(FormatError, "Unable to output '%%%%'!"); } pos += off; fmt += 2; continue; } /* Match Format Specifier */ while(!strchr("diuoxXfFeEgGaAxcsp$\0", *fmt)) { fmt++; } if (start != fmt) { strncpy(fmt_buf, start, (fmt - start)+1); fmt_buf[(fmt - start)+1] = '\0'; var a = va_arg(va, var); if (*fmt == '$') { pos = show_to(a, out, pos); } if (*fmt == 's') { int off = format_to(out, pos, fmt_buf, as_str(a)); if (off < 0) { throw(FormatError, "Unable to output String!"); } pos += off; } if (strchr("diouxX", *fmt)) { int off = format_to(out, pos, fmt_buf, as_long(a)); if (off < 0) { throw(FormatError, "Unable to output Int!"); } pos += off; } if (strchr("fFeEgGaA", *fmt)) { int off = format_to(out, pos, fmt_buf, as_double(a)); if (off < 0) { throw(FormatError, "Unable to output Real!"); } pos += off; } if (*fmt == 'c') { int off = format_to(out, pos, fmt_buf, as_char(a)); if (off < 0) { throw(FormatError, "Unable to output Char!"); } pos += off; } if (*fmt == 'p') { int off = format_to(out, pos, fmt_buf, a); if (off < 0) { throw(FormatError, "Unable to output Object!"); } pos += off; } fmt++; continue; } throw(FormatError, "Invalid Format String!"); } return pos; }
void Int_Assign(var self, var obj) { IntData* intdata = cast(self, Int); intdata->value = as_long(obj); }
void Int_Div(var self, var other) { IntData* io = cast(self, Int); io->value /= as_long(other); }
void Int_Mul(var self, var other) { IntData* io = cast(self, Int); io->value *= as_long(other); }
void Int_Sub(var self, var other) { IntData* io = cast(self, Int); io->value -= as_long(other); }
void Int_Add(var self, var other) { IntData* io = cast(self, Int); io->value += as_long(other); }
var Int_Lt(var self, var other) { IntData* io = cast(self, Int); return (var)(intptr_t)(io->value < as_long(other)); }
long as_long_suffix() const { return as_long(true); }
closure_value & operator<<= (closure_value const &rhs) { switch (type) { case is_bool: case is_int: switch (rhs.type) { case is_bool: case is_int: { long shift_by = as_long(rhs); if (shift_by > 64) shift_by = 64; else if (shift_by < -64) shift_by = -64; value.i <<= shift_by; } break; case is_uint: { unsigned long shift_by = as_ulong(rhs); if (shift_by > 64) shift_by = 64; value.ui <<= shift_by; // Note: The usual arithmetic conversions are not performed on // bit shift operations. } break; } break; case is_uint: switch (rhs.type) { case is_bool: case is_int: { long shift_by = as_long(rhs); if (shift_by > 64) shift_by = 64; else if (shift_by < -64) shift_by = -64; value.ui <<= shift_by; } break; case is_uint: { unsigned long shift_by = as_ulong(rhs); if (shift_by > 64) shift_by = 64; value.ui <<= shift_by; } break; } } valid = (value_error)(valid | rhs.valid); return *this; }
// arithmetics closure_value &operator+= (closure_value const &rhs) { switch (type) { case is_int: switch(rhs.type) { case is_bool: { int_literal_type result = value.i + as_long(rhs); if ((rhs.value.i > 0L && value.i > result) || (rhs.value.i < 0L && value.i < result)) { valid = error_integer_overflow; } else { value.i = result; } } break; case is_int: { int_literal_type result = value.i + rhs.value.i; if ((rhs.value.i > 0L && value.i > result) || (rhs.value.i < 0L && value.i < result)) { valid = error_integer_overflow; } else { value.i = result; } } break; case is_uint: { uint_literal_type result = value.ui + rhs.value.ui; if (result < value.ui) { valid = error_integer_overflow; } else { value.ui = result; type = is_uint; } } break; } break; case is_uint: { uint_literal_type result = value.ui + as_ulong(rhs); if (result < value.ui) { valid = error_integer_overflow; } else { value.ui = result; } } break; case is_bool: value.i = value.b + as_bool(rhs); type = is_int; } valid = (value_error)(valid | rhs.valid); return *this; }