diff --git a/doc/Literals.md b/doc/Literals.md index a464bfb4..a7ee42b4 100644 --- a/doc/Literals.md +++ b/doc/Literals.md @@ -16,6 +16,10 @@ This page explains literals. boolean: 'true' | 'false' ; +`false` is an alias for `null`. +The only falsy value is `null`. The other values are all truthy. +`true` is the value that is just truthy. + ## Integer Literals integer: digit+ ; diff --git a/doc/StackUsage.md b/doc/StackUsage.md index cb5a4955..ba66b8d4 100644 --- a/doc/StackUsage.md +++ b/doc/StackUsage.md @@ -104,7 +104,7 @@ NUL | |N - BOOLEAN + TRUE | |B INTEGER diff --git a/doc/TermExpressions.md b/doc/TermExpressions.md index 8f857ed6..87e3ca35 100644 --- a/doc/TermExpressions.md +++ b/doc/TermExpressions.md @@ -10,6 +10,8 @@ See [PrimaryExpressions](PrimaryExpressions.md). unary: ('+' | '-' | '!' | '~')* primary ; +Negate operator (`!`) returns `true` if the operand is `false` (`null`), returns `false` (`null`) otherwise. + ## Multiplicative Expressions multiplicative: unary (('*' | '/' | '%') unary)* ; @@ -26,13 +28,21 @@ See [PrimaryExpressions](PrimaryExpressions.md). relational: shift (('<' | '>' | '<=' | '>=') shift)* ; +Relational, equality, and identity operators return either `true` or `false` (`null`). + ## Equality Expressions equality: relational (('==' | '!=') relational)* ; +## Identity Expressions + + identity: equality (('===' | '!==') equality)* ; + ## And Expressions - and: equality ('&' equality)* ; + and: identity ('&' identity)* ; + +Bitwise operators (`&`, `^`, and `|`) do bitwise operations if both the operands are integers, do boolean operations if the left operand is boolean (`true`, `false`, or `null`), throws an exception otherwise. ## Xor Expressions @@ -46,10 +56,14 @@ See [PrimaryExpressions](PrimaryExpressions.md). and_also: or ('&&' or)* ; +Evaluates the left operand, returns it if it is `false` (`null`), evaluates the right operand and returns it otherwise. + ## Or Else Expressions or_else: and_also ('||' and_also)* ; +Evaluates the left operand, returns it if it is not `false` (`null`), evaluates the right operand and returns it otherwise. + ## Conditional Expressions conditional: or_else ('?' conditional ':' conditional)? ; diff --git a/doc/WalkThrough.md b/doc/WalkThrough.md index 6aebfdac..3c965b58 100644 --- a/doc/WalkThrough.md +++ b/doc/WalkThrough.md @@ -13,7 +13,7 @@ This document walks through xemmai language. "This is a string." null true - false + false # => null ## Variables diff --git a/include/xemmai/ast.h b/include/xemmai/ast.h index d3787570..9d0d6a60 100644 --- a/include/xemmai/ast.h +++ b/include/xemmai/ast.h @@ -72,32 +72,22 @@ struct t_operand e_tag__TEMPORARY }; - static inline const t_pvalue v_null{}; - static inline const t_pvalue v_true{true}; - static inline const t_pvalue v_false{false}; - t_tag v_tag; union { intptr_t v_integer; double v_float; - const t_pvalue* v_value; + t_object* v_value; size_t v_index; }; - t_operand(nullptr_t) : v_tag(e_tag__LITERAL), v_value(&v_null) - { - } - t_operand(bool a_value) : v_tag(e_tag__LITERAL), v_value(a_value ? &v_true : &v_false) - { - } t_operand(intptr_t a_value) : v_tag(e_tag__INTEGER), v_integer(a_value) { } t_operand(double a_value) : v_tag(e_tag__FLOAT), v_float(a_value) { } - t_operand(t_svalue& a_value) : v_tag(e_tag__LITERAL), v_value(reinterpret_cast(&a_value)) + t_operand(t_object* a_value) : v_tag(e_tag__LITERAL), v_value(a_value) { } t_operand() : v_tag(e_tag__TEMPORARY) @@ -163,6 +153,7 @@ struct t_lambda : t_node, t_scope struct t_if : t_node { std::unique_ptr v_condition; + bool v_preserve; std::vector> v_true; std::vector> v_false; t_block v_block_true; @@ -170,7 +161,7 @@ struct t_if : t_node t_block v_junction; t_block v_block_exit; - t_if(const t_at& a_at, std::unique_ptr&& a_condition) : t_node(a_at), v_condition(std::move(a_condition)) + t_if(const t_at& a_at, std::unique_ptr&& a_condition, bool a_preserve = false) : t_node(a_at), v_condition(std::move(a_condition)), v_preserve(a_preserve) { } virtual void f_flow(t_flow& a_flow); @@ -417,11 +408,16 @@ struct t_super : t_node virtual t_operand f_emit(t_emit& a_emit, bool a_tail, bool a_operand, bool a_clear); }; -struct t_null : t_node +struct t_boolean : t_node { - using t_node::t_node; + bool v_value; + + t_boolean(const t_at& a_at, bool a_value = false) : t_node(a_at), v_value(a_value) + { + } virtual t_operand f_emit(t_emit& a_emit, bool a_tail, bool a_operand, bool a_clear); }; +using t_null = t_boolean; template struct t_literal : t_node @@ -568,11 +564,6 @@ struct XEMMAI__LOCAL t_emit v_code->v_instructions.push_back(reinterpret_cast(a_operand)); return *this; } - t_emit& operator<<(bool a_operand) - { - v_code->v_instructions.push_back(reinterpret_cast(a_operand ? 1 : 0)); - return *this; - } t_emit& operator<<(double a_operand) { union @@ -584,14 +575,9 @@ struct XEMMAI__LOCAL t_emit for (size_t i = 0; i < sizeof(double) / sizeof(void*); ++i) v_code->v_instructions.push_back(v1[i]); return *this; } - t_emit& operator<<(const t_pvalue& a_operand) + t_emit& operator<<(t_object* a_operand) { - v_code->v_instructions.push_back(const_cast(&a_operand)); - return *this; - } - t_emit& operator<<(t_svalue& a_operand) - { - v_code->v_instructions.push_back(&a_operand); + v_code->v_instructions.push_back(a_operand); return *this; } t_emit& operator<<(t_label& a_label) @@ -618,9 +604,9 @@ struct XEMMAI__LOCAL t_emit { v_code->v_ats.push_back({a_node->v_at, f_last()}); } - void f_emit_null() + t_emit& f_emit_null() { - (*this << e_instruction__NUL << v_stack).f_push(); + return (*this << e_instruction__NUL << v_stack).f_push(); } void f_emit_safe_point(ast::t_node* a_node) { @@ -636,11 +622,6 @@ struct XEMMAI__LOCAL t_emit } }; -template<> -constexpr t_instruction t_emit::f_instruction_of() -{ - return e_instruction__BOOLEAN; -} template<> constexpr t_instruction t_emit::f_instruction_of() { @@ -662,7 +643,7 @@ t_operand t_literal::f_emit(t_emit& a_emit, bool a_tail, bool a_operand, bool if (a_clear) return {}; if (a_tail) { a_emit.f_emit_safe_point(this); - a_emit << static_cast(t_emit::f_instruction_of() + e_instruction__RETURN_BOOLEAN - e_instruction__BOOLEAN) << v_value; + a_emit << static_cast(t_emit::f_instruction_of() + e_instruction__RETURN_NUL - e_instruction__NUL) << v_value; } else { a_emit << t_emit::f_instruction_of() << a_emit.v_stack << v_value; } diff --git a/include/xemmai/boolean.h b/include/xemmai/boolean.h index fe56c268..a2cf5b6d 100644 --- a/include/xemmai/boolean.h +++ b/include/xemmai/boolean.h @@ -1,7 +1,7 @@ #ifndef XEMMAI__BOOLEAN_H #define XEMMAI__BOOLEAN_H -#include "object.h" +#include "string.h" namespace xemmai { @@ -14,18 +14,17 @@ struct t_type_of : t_uninstantiatable> { static bool f_as(auto&& a_object) { - return a_object.f_boolean(); + return a_object; } static bool f_is(t_object* a_object) { - return reinterpret_cast(a_object) == e_tag__BOOLEAN; + return true; } }; - XEMMAI__PUBLIC static t_object* f__string(bool a_self); - static intptr_t f__hash(bool a_self) + static t_object* f__string(bool a_self) { - return a_self ? 1 : 0; + return t_string::f_instantiate(a_self ? L"true"sv : L"null"sv); } XEMMAI__LOCAL static void f_define(); diff --git a/include/xemmai/class.h b/include/xemmai/class.h index 634199a8..1f549d31 100644 --- a/include/xemmai/class.h +++ b/include/xemmai/class.h @@ -15,7 +15,7 @@ struct t_type_of : t_uninstantiatable> f_finalize = f_do_scan; v_get = static_cast(&t_type_of::f_do_get); f_string = f_hash = f_not_supported0; - f_get_at = f_set_at = f_plus = f_minus = f_not = f_complement = f_multiply = f_divide = f_modulus = f_subtract = f_left_shift = f_right_shift = f_less = f_less_equal = f_greater = f_greater_equal = f_equals = f_not_equals = f_and = f_xor = f_or = f_not_supported1; + f_get_at = f_set_at = f_plus = f_minus = f_complement = f_multiply = f_divide = f_modulus = f_subtract = f_left_shift = f_right_shift = f_less = f_less_equal = f_greater = f_greater_equal = f_equals = f_not_equals = f_and = f_xor = f_or = f_not_supported1; } static void f_do_scan(t_object* a_this, t_scan a_scan); XEMMAI__PUBLIC t_pvalue f_do_get(t_object* a_this, t_object* a_key, size_t& a_index); diff --git a/include/xemmai/code.h b/include/xemmai/code.h index 1024d137..e877f7e4 100644 --- a/include/xemmai/code.h +++ b/include/xemmai/code.h @@ -40,12 +40,12 @@ enum t_instruction e_instruction__CLASS, e_instruction__SUPER, e_instruction__NUL, - e_instruction__BOOLEAN, + e_instruction__TRU, e_instruction__INTEGER, e_instruction__FLOAT, e_instruction__INSTANCE, e_instruction__RETURN_NUL, - e_instruction__RETURN_BOOLEAN, + e_instruction__RETURN_TRU, e_instruction__RETURN_INTEGER, e_instruction__RETURN_FLOAT, e_instruction__RETURN_INSTANCE, diff --git a/include/xemmai/fiber.h b/include/xemmai/fiber.h index cbe62771..6206a3d7 100644 --- a/include/xemmai/fiber.h +++ b/include/xemmai/fiber.h @@ -265,7 +265,7 @@ inline t_pvalue t_value::f_##a_name() const\ auto p = static_cast(*this);\ switch (reinterpret_cast(p)) {\ case e_tag__NULL:\ - case e_tag__BOOLEAN:\ + case e_tag__TRUE:\ f_throw(L"not supported."sv);\ case e_tag__INTEGER:\ return a_operator(v_integer);\ @@ -279,22 +279,6 @@ inline t_pvalue t_value::f_##a_name() const\ XEMMAI__VALUE__UNARY_ARITHMETIC(plus, ) XEMMAI__VALUE__UNARY_ARITHMETIC(minus, -) -template -inline t_pvalue t_value::f_not() const -{ - auto p = static_cast(*this); - switch (reinterpret_cast(p)) { - case e_tag__BOOLEAN: - return !v_boolean; - case e_tag__NULL: - case e_tag__INTEGER: - case e_tag__FLOAT: - f_throw(L"not supported."sv); - default: - XEMMAI__VALUE__UNARY(f_not) - } -} - template inline t_pvalue t_value::f_complement() const { @@ -303,7 +287,7 @@ inline t_pvalue t_value::f_complement() const case e_tag__INTEGER: return ~v_integer; case e_tag__NULL: - case e_tag__BOOLEAN: + case e_tag__TRUE: case e_tag__FLOAT: f_throw(L"not supported."sv); default: diff --git a/include/xemmai/float.h b/include/xemmai/float.h index 7c05867e..35d2ee0a 100644 --- a/include/xemmai/float.h +++ b/include/xemmai/float.h @@ -42,7 +42,7 @@ struct t_type_of : t_derivable, t_derived_primitive::t_type, double>) return reinterpret_cast(a_object) >= e_tag__OBJECT && a_object->f_type()->f_derives::t_type>(); switch (reinterpret_cast(a_object)) { case e_tag__NULL: - case e_tag__BOOLEAN: + case e_tag__TRUE: return false; case e_tag__INTEGER: case e_tag__FLOAT: diff --git a/include/xemmai/global.h b/include/xemmai/global.h index bfa313d3..bb6a2940 100644 --- a/include/xemmai/global.h +++ b/include/xemmai/global.h @@ -4,7 +4,6 @@ #include "engine.h" #include "native.h" #include "method.h" -#include "null.h" #include "list.h" #include "map.h" #include "bytes.h" @@ -39,7 +38,6 @@ class t_global : public t_library t_slot_of v_type_advanced_lambda_shared; t_slot_of v_type_method; t_slot_of v_type_throwable; - t_slot_of v_type_null; t_slot_of v_type_boolean; t_slot_of v_type_integer; t_slot_of v_type_float; @@ -59,7 +57,6 @@ class t_global : public t_library t_slot v_symbol_set_at; t_slot v_symbol_plus; t_slot v_symbol_minus; - t_slot v_symbol_not; t_slot v_symbol_complement; t_slot v_symbol_multiply; t_slot v_symbol_divide; @@ -121,10 +118,6 @@ class t_global : public t_library { return v_symbol_minus; } - t_object* f_symbol_not() const - { - return v_symbol_not; - } t_object* f_symbol_complement() const { return v_symbol_complement; @@ -221,7 +214,6 @@ XEMMAI__LIBRARY__TYPE_AS(t_global, t_advanced_lambda, advanced_lambda) XEMMAI__LIBRARY__TYPE_AS(t_global, t_advanced_lambda, advanced_lambda_shared) XEMMAI__LIBRARY__TYPE(t_global, method) XEMMAI__LIBRARY__TYPE(t_global, throwable) -XEMMAI__LIBRARY__TYPE_AS(t_global, std::nullptr_t, null) XEMMAI__LIBRARY__TYPE_AS(t_global, bool, boolean) XEMMAI__LIBRARY__TYPE_AS(t_global, intptr_t, integer) XEMMAI__LIBRARY__TYPE_AS(t_global, double, float) @@ -249,8 +241,7 @@ XEMMAI__PORTABLE__ALWAYS_INLINE inline t_type* t_value::f_type() const auto p = static_cast(*this); switch (reinterpret_cast(p)) { case e_tag__NULL: - return f_global()->f_type(); - case e_tag__BOOLEAN: + case e_tag__TRUE: return f_global()->f_type(); case e_tag__INTEGER: return f_global()->f_type(); @@ -286,9 +277,8 @@ inline t_pvalue t_value::f_##a_name() const\ auto p = static_cast(*this);\ switch (reinterpret_cast(p)) {\ case e_tag__NULL:\ - return t_type_of::f__##a_name(*this);\ - case e_tag__BOOLEAN:\ - return t_type_of::f__##a_name(v_boolean);\ + case e_tag__TRUE:\ + return t_type_of::f__##a_name(*this);\ case e_tag__INTEGER:\ return t_type_of::f__##a_name(v_integer);\ case e_tag__FLOAT:\ @@ -320,7 +310,7 @@ inline t_pvalue t_value::f_##a_name(const t_pvalue& a_value) const\ auto p = static_cast(*this);\ switch (reinterpret_cast(p)) {\ case e_tag__NULL:\ - case e_tag__BOOLEAN:\ + case e_tag__TRUE:\ f_throw(L"not supported."sv);\ case e_tag__INTEGER:\ return t_type_of::f__##a_name(v_integer, a_value);\ @@ -341,7 +331,7 @@ inline t_pvalue t_value::f_##a_name(const t_pvalue& a_value) const\ f_check(a_value, L"argument0");\ return static_cast(v_integer) a_operator f_as(a_value);\ case e_tag__NULL:\ - case e_tag__BOOLEAN:\ + case e_tag__TRUE:\ case e_tag__FLOAT:\ f_throw(L"not supported."sv);\ default:\ @@ -355,9 +345,8 @@ inline t_pvalue t_value::f_##a_name(const t_pvalue& a_value) const\ auto p = static_cast(*this);\ switch (reinterpret_cast(p)) {\ case e_tag__NULL:\ + case e_tag__TRUE:\ return a_operator(p == a_value.v_p);\ - case e_tag__BOOLEAN:\ - return a_operator(p == a_value.v_p && v_boolean == a_value.v_boolean);\ case e_tag__INTEGER:\ return t_type_of::f__##a_name(v_integer, a_value);\ case e_tag__FLOAT:\ @@ -372,13 +361,12 @@ inline t_pvalue t_value::f_##a_name(const t_pvalue& a_value) const\ {\ auto p = static_cast(*this);\ switch (reinterpret_cast(p)) {\ - case e_tag__BOOLEAN:\ - f_check(a_value, L"argument0");\ - return static_cast(v_boolean a_operator f_as(a_value));\ + case e_tag__NULL:\ + case e_tag__TRUE:\ + return static_cast(static_cast(p) a_operator f_as(a_value));\ case e_tag__INTEGER:\ f_check(a_value, L"argument0");\ return v_integer a_operator f_as(a_value);\ - case e_tag__NULL:\ case e_tag__FLOAT:\ f_throw(L"not supported."sv);\ default:\ diff --git a/include/xemmai/integer.h b/include/xemmai/integer.h index 6ab095b7..9ce7a399 100644 --- a/include/xemmai/integer.h +++ b/include/xemmai/integer.h @@ -38,7 +38,7 @@ struct t_type_of : t_derivable, t_derived_primitive< case e_tag__INTEGER: return true; case e_tag__NULL: - case e_tag__BOOLEAN: + case e_tag__TRUE: case e_tag__FLOAT: return false; default: diff --git a/include/xemmai/module.h b/include/xemmai/module.h index 5bdaca8f..39fe3285 100644 --- a/include/xemmai/module.h +++ b/include/xemmai/module.h @@ -42,20 +42,19 @@ struct t_module struct t_script : t_module::t_body { std::wstring v_path; - std::deque v_slots; + std::deque v_slots; std::mutex v_mutex; t_script(std::wstring_view a_path) : v_path(a_path) { } virtual void f_scan(t_scan a_scan); - t_svalue& f_slot(t_object* a_p) + t_object* f_slot(t_object* a_p) { v_mutex.lock(); auto& p = v_slots.emplace_back(); v_mutex.unlock(); - p = a_p; - return p; + return p = a_p; } }; diff --git a/include/xemmai/null.h b/include/xemmai/null.h deleted file mode 100644 index 3a64e2b0..00000000 --- a/include/xemmai/null.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef XEMMAI__NULL_H -#define XEMMAI__NULL_H - -#include "string.h" - -namespace xemmai -{ - -template<> -struct t_type_of : t_uninstantiatable> -{ - static t_object* f__string(const t_pvalue&) - { - return t_string::f_instantiate(L"null"sv); - } - XEMMAI__LOCAL static void f_define(); - - using t_base::t_base; -}; - -} - -#endif diff --git a/include/xemmai/object.h b/include/xemmai/object.h index d440c1dc..9aa50865 100644 --- a/include/xemmai/object.h +++ b/include/xemmai/object.h @@ -356,7 +356,7 @@ struct t_type::t_cast switch (reinterpret_cast(a_object)) { case e_tag__NULL: return true; - case e_tag__BOOLEAN: + case e_tag__TRUE: case e_tag__INTEGER: case e_tag__FLOAT: return false; diff --git a/include/xemmai/parser.h b/include/xemmai/parser.h index eb0ce1b6..c364f727 100644 --- a/include/xemmai/parser.h +++ b/include/xemmai/parser.h @@ -30,7 +30,7 @@ class XEMMAI__LOCAL t_parser { f_throw(a_message, v_lexer.f_at()); } - t_svalue& f_symbol() const + t_object* f_symbol() const { return v_module.f_slot(t_symbol::f_instantiate(v_lexer.f_value())); } diff --git a/include/xemmai/type.h b/include/xemmai/type.h index 5f33823f..03b1db02 100644 --- a/include/xemmai/type.h +++ b/include/xemmai/type.h @@ -109,7 +109,7 @@ struct t_type_of static XEMMAI__TYPE__IDS_MODIFIER std::array V_ids{f_type_id()}; static constexpr size_t V_native = 0; - static constexpr size_t V_fields = 26; + static constexpr size_t V_fields = 25; static t_pvalue f_transfer(auto* a_library, auto&& a_value) { @@ -130,6 +130,18 @@ struct t_type_of { return a_self != a_other; } + static bool f__and(const t_pvalue& a_self, const t_pvalue& a_other) + { + return a_other; + } + static bool f__xor(const t_pvalue& a_self, const t_pvalue& a_other) + { + return !a_other; + } + static bool f__or(const t_pvalue& a_self, const t_pvalue& a_other) + { + return true; + } XEMMAI__LOCAL void f_define(); t_slot v_this; @@ -229,8 +241,6 @@ struct t_type_of size_t (*f_plus)(t_object*, t_pvalue*) = f_do_plus; XEMMAI__PUBLIC static size_t f_do_minus(t_object* a_this, t_pvalue* a_stack); size_t (*f_minus)(t_object*, t_pvalue*) = f_do_minus; - XEMMAI__PUBLIC static size_t f_do_not(t_object* a_this, t_pvalue* a_stack); - size_t (*f_not)(t_object*, t_pvalue*) = f_do_not; XEMMAI__PUBLIC static size_t f_do_complement(t_object* a_this, t_pvalue* a_stack); size_t (*f_complement)(t_object*, t_pvalue*) = f_do_complement; XEMMAI__PUBLIC static size_t f_do_multiply(t_object* a_this, t_pvalue* a_stack); @@ -278,7 +288,6 @@ struct t_type_of if (T::f_do_set_at != U::f_do_set_at) f_set_at = T::f_do_set_at; if (T::f_do_plus != U::f_do_plus) f_plus = T::f_do_plus; if (T::f_do_minus != U::f_do_minus) f_minus = T::f_do_minus; - if (T::f_do_not != U::f_do_not) f_not = T::f_do_not; if (T::f_do_complement != U::f_do_complement) f_complement = T::f_do_complement; if (T::f_do_multiply != U::f_do_multiply) f_multiply = T::f_do_multiply; if (T::f_do_divide != U::f_do_divide) f_divide = T::f_do_divide; @@ -399,7 +408,6 @@ struct t_derived : T this->f_set_at = t_type::f_do_set_at; this->f_plus = t_type::f_do_plus; this->f_minus = t_type::f_do_minus; - this->f_not = t_type::f_do_not; this->f_complement = t_type::f_do_complement; this->f_multiply = t_type::f_do_multiply; this->f_divide = t_type::f_do_divide; diff --git a/include/xemmai/value.h b/include/xemmai/value.h index 950fb3a9..5c36d03d 100644 --- a/include/xemmai/value.h +++ b/include/xemmai/value.h @@ -21,7 +21,7 @@ using t_type = t_type_of; enum t_tag { e_tag__NULL, - e_tag__BOOLEAN, + e_tag__TRUE, e_tag__INTEGER, e_tag__FLOAT, e_tag__OBJECT @@ -236,7 +236,6 @@ class t_value : public T_tag union { - bool v_boolean; intptr_t v_integer; double v_float; }; @@ -251,7 +250,7 @@ class t_value : public T_tag public: using T_tag::T_tag; - t_value(bool a_value) : T_tag(reinterpret_cast(e_tag__BOOLEAN)), v_boolean(a_value) + t_value(bool a_value) : T_tag(reinterpret_cast(a_value ? e_tag__TRUE : e_tag__NULL)) { } template, bool> = true> @@ -289,8 +288,6 @@ class t_value : public T_tag auto p = f_tag(); if (p != a_value.f_tag()) return false; switch (p) { - case e_tag__BOOLEAN: - return v_boolean == a_value.v_boolean; case e_tag__INTEGER: return v_integer == a_value.v_integer; case e_tag__FLOAT: @@ -307,10 +304,6 @@ class t_value : public T_tag { return reinterpret_cast(static_cast(*this)); } - bool f_boolean() const - { - return v_boolean; - } intptr_t f_integer() const; double f_float() const; t_type_of* f_type() const; @@ -346,7 +339,6 @@ class t_value : public T_tag t_value f_set_at(const t_value& a_index, const t_value& a_value) const; t_value f_plus() const; t_value f_minus() const; - t_value f_not() const; t_value f_complement() const; t_value f_multiply(const t_value& a_value) const; t_value f_divide(const t_value& a_value) const; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d0c2fea2..f4277c0e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,7 +12,6 @@ add_executable(xemmai code.cc lambda.cc throwable.cc - null.cc boolean.cc integer.cc float.cc diff --git a/src/ast.cc b/src/ast.cc index dcf0f64d..3bb24268 100644 --- a/src/ast.cc +++ b/src/ast.cc @@ -9,12 +9,12 @@ namespace ast namespace { -void f_emit_block(t_emit& a_emit, const std::vector>& a_nodes, bool a_tail, bool a_clear) +void f_emit_block(t_emit& a_emit, const std::vector>& a_nodes, bool a_tail, bool a_clear, bool a_preserve = false) { auto i = a_nodes.begin(); auto j = a_nodes.end(); if (i == j) { - if (!a_clear) a_emit.f_emit_null(); + if (!a_clear) a_preserve ? a_emit.f_push() : a_emit.f_emit_null(); } else { for (--j; i != j; ++i) (*i)->f_emit(a_emit, false, false, true); (*i)->f_emit(a_emit, a_tail, false, a_clear); @@ -214,14 +214,14 @@ t_operand t_if::f_emit(t_emit& a_emit, bool a_tail, bool a_operand, bool a_clear a_emit << e_instruction__BRANCH << a_emit.v_stack << label0; auto privates = *a_emit.v_privates; auto stack = a_emit.v_stack; - f_emit_block(a_emit, v_true, a_tail, a_clear); + f_emit_block(a_emit, v_true, a_tail, a_clear, v_preserve); a_emit.f_join(v_junction); auto& label1 = a_emit.f_label(); a_emit << e_instruction__JUMP << label1; a_emit.f_target(label0); *a_emit.v_privates = privates; a_emit.v_stack = stack; - f_emit_block(a_emit, v_false, a_tail, a_clear); + f_emit_block(a_emit, v_false, a_tail, a_clear, v_preserve); a_emit.f_join(v_junction); a_emit.f_target(label1); a_emit.f_merge(v_junction); @@ -717,15 +717,15 @@ t_operand t_scope_put::f_emit(t_emit& a_emit, bool a_tail, bool a_operand, bool a_emit << e_instruction__FLOAT << v_variable.v_index << operand.v_float; break; case t_operand::e_tag__LITERAL: - switch (operand.v_value->f_tag()) { + switch (reinterpret_cast(operand.v_value)) { case e_tag__NULL: a_emit << e_instruction__NUL << v_variable.v_index; break; - case e_tag__BOOLEAN: - a_emit << e_instruction__BOOLEAN << v_variable.v_index << operand.v_value->f_boolean(); + case e_tag__TRUE: + a_emit << e_instruction__TRU << v_variable.v_index; break; default: - a_emit << e_instruction__INSTANCE << v_variable.v_index << *operand.v_value; + a_emit << e_instruction__INSTANCE << v_variable.v_index << operand.v_value; } break; case t_operand::e_tag__VARIABLE: @@ -802,15 +802,15 @@ t_operand t_super::f_emit(t_emit& a_emit, bool a_tail, bool a_operand, bool a_cl return {}; } -t_operand t_null::f_emit(t_emit& a_emit, bool a_tail, bool a_operand, bool a_clear) +t_operand t_boolean::f_emit(t_emit& a_emit, bool a_tail, bool a_operand, bool a_clear) { - if (a_operand) return nullptr; + if (a_operand) return reinterpret_cast(static_cast(v_value)); if (a_clear) return {}; if (a_tail) { a_emit.f_emit_safe_point(this); - (a_emit << e_instruction__RETURN_NUL).f_push(); + (a_emit << static_cast(e_instruction__RETURN_NUL + v_value)).f_push(); } else { - a_emit.f_emit_null(); + (a_emit << static_cast(e_instruction__NUL + v_value) << a_emit.v_stack).f_push(); } a_emit.f_at(this); return {}; @@ -832,10 +832,12 @@ t_operand t_unary::f_emit(t_emit& a_emit, bool a_tail, bool a_operand, bool a_cl return t_literal(v_at, operand.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__MINUS_T: return t_literal(v_at, -operand.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); + case e_instruction__NOT_T: + return t_null(v_at).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__COMPLEMENT_T: return t_literal(v_at, ~operand.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); default: - f_throw(L"not supported."sv); + assert(false); } } else if (operand.v_tag == t_operand::e_tag__FLOAT) { a_emit.f_pop(); @@ -844,6 +846,8 @@ t_operand t_unary::f_emit(t_emit& a_emit, bool a_tail, bool a_operand, bool a_cl return t_literal(v_at, operand.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__MINUS_T: return t_literal(v_at, -operand.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); + case e_instruction__NOT_T: + return t_null(v_at).f_emit(a_emit, a_tail, a_operand, a_clear); default: f_throw(L"not supported."sv); } @@ -866,7 +870,7 @@ t_operand t_unary::f_emit(t_emit& a_emit, bool a_tail, bool a_operand, bool a_cl if (!a_tail) a_emit << a_emit.v_stack; switch (operand.v_tag) { case t_operand::e_tag__LITERAL: - a_emit << *operand.v_value; + a_emit << operand.v_value; break; case t_operand::e_tag__VARIABLE: a_emit << operand.v_index; @@ -908,19 +912,19 @@ t_operand t_binary::f_emit(t_emit& a_emit, bool a_tail, bool a_operand, bool a_c case e_instruction__RIGHT_SHIFT_TT: return t_literal(v_at, static_cast(left.v_integer) >> right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__LESS_TT: - return t_literal(v_at, left.v_integer < right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, left.v_integer < right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__LESS_EQUAL_TT: - return t_literal(v_at, left.v_integer <= right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, left.v_integer <= right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__GREATER_TT: - return t_literal(v_at, left.v_integer > right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, left.v_integer > right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__GREATER_EQUAL_TT: - return t_literal(v_at, left.v_integer >= right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, left.v_integer >= right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__EQUALS_TT: case e_instruction__IDENTICAL_TT: - return t_literal(v_at, left.v_integer == right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, left.v_integer == right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__NOT_EQUALS_TT: case e_instruction__NOT_IDENTICAL_TT: - return t_literal(v_at, left.v_integer != right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, left.v_integer != right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__AND_TT: return t_literal(v_at, left.v_integer & right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__XOR_TT: @@ -928,7 +932,7 @@ t_operand t_binary::f_emit(t_emit& a_emit, bool a_tail, bool a_operand, bool a_c case e_instruction__OR_TT: return t_literal(v_at, left.v_integer | right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); default: - f_throw(L"not supported."sv); + assert(false); } } else if (right.v_tag == t_operand::e_tag__FLOAT) { a_emit.f_pop(); @@ -942,21 +946,21 @@ t_operand t_binary::f_emit(t_emit& a_emit, bool a_tail, bool a_operand, bool a_c case e_instruction__SUBTRACT_TT: return t_literal(v_at, left.v_integer - right.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__LESS_TT: - return t_literal(v_at, left.v_integer < right.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, left.v_integer < right.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__LESS_EQUAL_TT: - return t_literal(v_at, left.v_integer <= right.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, left.v_integer <= right.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__GREATER_TT: - return t_literal(v_at, left.v_integer > right.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, left.v_integer > right.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__GREATER_EQUAL_TT: - return t_literal(v_at, left.v_integer >= right.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, left.v_integer >= right.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__EQUALS_TT: - return t_literal(v_at, left.v_integer == right.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, left.v_integer == right.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__NOT_EQUALS_TT: - return t_literal(v_at, left.v_integer != right.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, left.v_integer != right.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__IDENTICAL_TT: - return t_literal(v_at, false).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, false).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__NOT_IDENTICAL_TT: - return t_literal(v_at, true).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, true).f_emit(a_emit, a_tail, a_operand, a_clear); default: f_throw(L"not supported."sv); } @@ -974,21 +978,21 @@ t_operand t_binary::f_emit(t_emit& a_emit, bool a_tail, bool a_operand, bool a_c case e_instruction__SUBTRACT_TT: return t_literal(v_at, left.v_float - right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__LESS_TT: - return t_literal(v_at, left.v_float < right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, left.v_float < right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__LESS_EQUAL_TT: - return t_literal(v_at, left.v_float <= right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, left.v_float <= right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__GREATER_TT: - return t_literal(v_at, left.v_float > right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, left.v_float > right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__GREATER_EQUAL_TT: - return t_literal(v_at, left.v_float >= right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, left.v_float >= right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__EQUALS_TT: - return t_literal(v_at, left.v_float == right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, left.v_float == right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__NOT_EQUALS_TT: - return t_literal(v_at, left.v_float != right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, left.v_float != right.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__IDENTICAL_TT: - return t_literal(v_at, false).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, false).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__NOT_IDENTICAL_TT: - return t_literal(v_at, true).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, true).f_emit(a_emit, a_tail, a_operand, a_clear); default: f_throw(L"not supported."sv); } @@ -1004,19 +1008,19 @@ t_operand t_binary::f_emit(t_emit& a_emit, bool a_tail, bool a_operand, bool a_c case e_instruction__SUBTRACT_TT: return t_literal(v_at, left.v_float - right.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__LESS_TT: - return t_literal(v_at, left.v_float < right.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, left.v_float < right.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__LESS_EQUAL_TT: - return t_literal(v_at, left.v_float <= right.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, left.v_float <= right.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__GREATER_TT: - return t_literal(v_at, left.v_float > right.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, left.v_float > right.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__GREATER_EQUAL_TT: - return t_literal(v_at, left.v_float >= right.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, left.v_float >= right.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__EQUALS_TT: case e_instruction__IDENTICAL_TT: - return t_literal(v_at, left.v_float == right.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, left.v_float == right.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); case e_instruction__NOT_EQUALS_TT: case e_instruction__NOT_IDENTICAL_TT: - return t_literal(v_at, left.v_float != right.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_boolean(v_at, left.v_float != right.v_float).f_emit(a_emit, a_tail, a_operand, a_clear); default: f_throw(L"not supported."sv); } @@ -1067,7 +1071,7 @@ t_operand t_binary::f_emit(t_emit& a_emit, bool a_tail, bool a_operand, bool a_c a_emit << left.v_float; break; case t_operand::e_tag__LITERAL: - a_emit << *left.v_value; + a_emit << left.v_value; break; case t_operand::e_tag__VARIABLE: a_emit << left.v_index; @@ -1081,7 +1085,7 @@ t_operand t_binary::f_emit(t_emit& a_emit, bool a_tail, bool a_operand, bool a_c a_emit << right.v_float; break; case t_operand::e_tag__LITERAL: - a_emit << *right.v_value; + a_emit << right.v_value; break; case t_operand::e_tag__VARIABLE: a_emit << right.v_index; diff --git a/src/boolean.cc b/src/boolean.cc index 1f867dac..f57424ad 100644 --- a/src/boolean.cc +++ b/src/boolean.cc @@ -3,11 +3,6 @@ namespace xemmai { -t_object* t_type_of::f__string(bool a_self) -{ - return t_string::f_instantiate(a_self ? L"true"sv : L"false"sv); -} - void t_type_of::f_define() { t_define{f_global()} diff --git a/src/code.cc b/src/code.cc index aea41096..197767e2 100644 --- a/src/code.cc +++ b/src/code.cc @@ -88,12 +88,12 @@ size_t t_code::f_loop(t_context* a_context, const void*** a_labels) &&label__CLASS, &&label__SUPER, &&label__NUL, - &&label__BOOLEAN, + &&label__TRU, &&label__INTEGER, &&label__FLOAT, &&label__INSTANCE, &&label__RETURN_NUL, - &&label__RETURN_BOOLEAN, + &&label__RETURN_TRU, &&label__RETURN_INTEGER, &&label__RETURN_FLOAT, &&label__RETURN_INSTANCE, @@ -454,12 +454,11 @@ size_t t_code::f_loop(t_context* a_context) stack[0] = nullptr; } XEMMAI__CODE__BREAK - XEMMAI__CODE__CASE(BOOLEAN) + XEMMAI__CODE__CASE(TRU) { auto stack = base + reinterpret_cast(*++pc); - auto value = reinterpret_cast(*++pc) != 0; ++pc; - stack[0] = value; + stack[0] = true; } XEMMAI__CODE__BREAK XEMMAI__CODE__CASE(INTEGER) @@ -488,7 +487,7 @@ size_t t_code::f_loop(t_context* a_context) XEMMAI__CODE__CASE(INSTANCE) { auto stack = base + reinterpret_cast(*++pc); - auto& value = *static_cast(*++pc); + auto value = static_cast(*++pc); ++pc; stack[0] = value; } @@ -496,8 +495,8 @@ size_t t_code::f_loop(t_context* a_context) XEMMAI__CODE__CASE(RETURN_NUL) a_context->f_return(nullptr); return -1; - XEMMAI__CODE__CASE(RETURN_BOOLEAN) - a_context->f_return(reinterpret_cast(*++pc) != 0); + XEMMAI__CODE__CASE(RETURN_TRU) + a_context->f_return(true); return -1; XEMMAI__CODE__CASE(RETURN_INTEGER) a_context->f_return(reinterpret_cast(*++pc)); @@ -509,7 +508,7 @@ size_t t_code::f_loop(t_context* a_context) } return -1; XEMMAI__CODE__CASE(RETURN_INSTANCE) - a_context->f_return(*static_cast(*++pc)); + a_context->f_return(static_cast(*++pc)); return -1; XEMMAI__CODE__CASE(RETURN_V) a_context->f_return(base[reinterpret_cast(*++pc)]); @@ -582,7 +581,7 @@ size_t t_code::f_loop(t_context* a_context) auto& a0 = stack[1]; #define XEMMAI__CODE__PREPARE() #define XEMMAI__CODE__FETCH_L()\ - auto& a0 = *static_cast(*++pc); + t_pvalue a0 = static_cast(*++pc); #define XEMMAI__CODE__PREPARE_L() #define XEMMAI__CODE__FETCH_V()\ auto& a0 = base[reinterpret_cast(*++pc)]; @@ -592,7 +591,7 @@ size_t t_code::f_loop(t_context* a_context) #define XEMMAI__CODE__PREPARE_A1()\ stack[2] = a1; #define XEMMAI__CODE__FETCH_LI()\ - auto& a0 = *static_cast(*++pc);\ + t_pvalue a0 = static_cast(*++pc);\ auto a1 = reinterpret_cast(*++pc); #define XEMMAI__CODE__PREPARE_LI() XEMMAI__CODE__PREPARE_A1() #define XEMMAI__CODE__FETCH_VI()\ @@ -604,7 +603,7 @@ size_t t_code::f_loop(t_context* a_context) auto a1 = reinterpret_cast(*++pc); #define XEMMAI__CODE__PREPARE_TI() XEMMAI__CODE__PREPARE_A1() #define XEMMAI__CODE__FETCH_LF()\ - auto& a0 = *static_cast(*++pc);\ + t_pvalue a0 = static_cast(*++pc);\ XEMMAI__CODE__FLOAT(a1, v1) #define XEMMAI__CODE__PREPARE_LF() XEMMAI__CODE__PREPARE_A1() #define XEMMAI__CODE__FETCH_VF()\ @@ -617,21 +616,21 @@ size_t t_code::f_loop(t_context* a_context) #define XEMMAI__CODE__PREPARE_TF() XEMMAI__CODE__PREPARE_A1() #define XEMMAI__CODE__FETCH_IL()\ auto a0 = reinterpret_cast(*++pc);\ - auto& a1 = *static_cast(*++pc); + t_pvalue a1 = static_cast(*++pc); #define XEMMAI__CODE__FETCH_FL()\ XEMMAI__CODE__FLOAT(a0, v0)\ - auto& a1 = *static_cast(*++pc); + t_pvalue a1 = static_cast(*++pc); #define XEMMAI__CODE__FETCH_LL()\ - auto& a0 = *static_cast(*++pc);\ - auto& a1 = *static_cast(*++pc); + t_pvalue a0 = static_cast(*++pc);\ + t_pvalue a1 = static_cast(*++pc); #define XEMMAI__CODE__PREPARE_LL() XEMMAI__CODE__PREPARE_A1() #define XEMMAI__CODE__FETCH_VL()\ auto& a0 = base[reinterpret_cast(*++pc)];\ - auto& a1 = *static_cast(*++pc); + t_pvalue a1 = static_cast(*++pc); #define XEMMAI__CODE__PREPARE_VL() XEMMAI__CODE__PREPARE_A1() #define XEMMAI__CODE__FETCH_TL()\ auto& a0 = stack[1];\ - auto& a1 = *static_cast(*++pc); + t_pvalue a1 = static_cast(*++pc); #define XEMMAI__CODE__PREPARE_TL() XEMMAI__CODE__PREPARE_A1() #define XEMMAI__CODE__FETCH_IV()\ auto a0 = reinterpret_cast(*++pc);\ @@ -640,7 +639,7 @@ size_t t_code::f_loop(t_context* a_context) XEMMAI__CODE__FLOAT(a0, v0)\ auto& a1 = base[reinterpret_cast(*++pc)]; #define XEMMAI__CODE__FETCH_LV()\ - auto& a0 = *static_cast(*++pc);\ + t_pvalue a0 = static_cast(*++pc);\ auto& a1 = base[reinterpret_cast(*++pc)]; #define XEMMAI__CODE__PREPARE_LV() XEMMAI__CODE__PREPARE_A1() #define XEMMAI__CODE__FETCH_VV()\ @@ -658,7 +657,7 @@ size_t t_code::f_loop(t_context* a_context) XEMMAI__CODE__FLOAT(a0, v0)\ auto& a1 = stack[1]; #define XEMMAI__CODE__FETCH_LT()\ - auto& a0 = *static_cast(*++pc);\ + t_pvalue a0 = static_cast(*++pc);\ auto& a1 = stack[1]; #define XEMMAI__CODE__PREPARE_LT() XEMMAI__CODE__PREPARE_A1() #define XEMMAI__CODE__FETCH_VT()\ diff --git a/src/code_operator.h b/src/code_operator.h index 349c9a5f..2f1c9eb7 100644 --- a/src/code_operator.h +++ b/src/code_operator.h @@ -13,12 +13,6 @@ } else {\ XEMMAI__CODE__PRIMITIVE_CALL(a_operator(false))\ } -#define XEMMAI__CODE__BOOLEAN_OR_THROW(a_operator)\ - if (a1.f_tag() == e_tag__BOOLEAN) {\ - XEMMAI__CODE__PRIMITIVE_CALL(static_cast(a0.v_boolean a_operator a1.v_boolean))\ - } else {\ - goto label__THROW_NOT_SUPPORTED;\ - } #define XEMMAI__CODE__OTHERS_OBJECT(a_name, a_method)\ XEMMAI__CODE__CASE_BEGIN(a_name)\ XEMMAI__CODE__OBJECT_OR_THROW(a_method)\ @@ -32,7 +26,7 @@ XEMMAI__CODE__CASE_BEGIN(a_name)\ switch (a0.f_tag()) {\ case e_tag__NULL:\ - case e_tag__BOOLEAN:\ + case e_tag__TRUE:\ goto label__THROW_NOT_SUPPORTED;\ case e_tag__INTEGER:\ XEMMAI__CODE__PRIMITIVE_CALL(a_operator(a0.v_integer))\ @@ -47,9 +41,7 @@ XEMMAI__CODE__UNARY_ARITHMETIC(PLUS, , f_plus) XEMMAI__CODE__UNARY_ARITHMETIC(MINUS, -, f_minus) XEMMAI__CODE__CASE_BEGIN(NOT) - if (a0.f_tag() == e_tag__BOOLEAN) { - XEMMAI__CODE__PRIMITIVE_CALL(!a0.v_boolean) - } else XEMMAI__CODE__OBJECT_OR_THROW(f_not) + XEMMAI__CODE__PRIMITIVE_CALL(!a0) XEMMAI__CODE__CASE_END XEMMAI__CODE__CASE_BEGIN(COMPLEMENT) if (a0.f_tag() == e_tag__INTEGER) { @@ -103,9 +95,14 @@ #define XEMMAI__CODE__BINARY_EQUALITY_PRIMITIVE(a_operator) #define XEMMAI__CODE__BINARY_BITWISE(a_name, a_operator, a_method)\ XEMMAI__CODE__CASE_BEGIN(a_name)\ - if (a0.f_tag() == e_tag__BOOLEAN) {\ - XEMMAI__CODE__BOOLEAN_OR_THROW(a_operator)\ - } else XEMMAI__CODE__OBJECT_OR_THROW(a_method)\ + switch (a0.f_tag()) {\ + case e_tag__NULL:\ + case e_tag__TRUE:\ + XEMMAI__CODE__PRIMITIVE_CALL(static_cast(f_as(a0) a_operator f_as(a1)))\ + break;\ + default:\ + XEMMAI__CODE__OBJECT_CALL(a_method)\ + }\ XEMMAI__CODE__CASE_END #else #ifdef XEMMAI__CODE__BINARY_XL @@ -147,7 +144,7 @@ XEMMAI__CODE__CASE_BEGIN(a_name)\ switch (a0.f_tag()) {\ case e_tag__NULL:\ - case e_tag__BOOLEAN:\ + case e_tag__TRUE:\ goto label__THROW_NOT_SUPPORTED;\ case e_tag__INTEGER:\ XEMMAI__CODE__BINARY_ARITHMETIC_INTEGER(a_operator)\ @@ -180,14 +177,14 @@ #define XEMMAI__CODE__BINARY_BITWISE(a_name, a_operator, a_method)\ XEMMAI__CODE__CASE_BEGIN(a_name)\ switch (a0.f_tag()) {\ - case e_tag__BOOLEAN:\ - XEMMAI__CODE__BOOLEAN_OR_THROW(a_operator)\ + case e_tag__NULL:\ + case e_tag__TRUE:\ + XEMMAI__CODE__PRIMITIVE_CALL(static_cast(f_as(a0) a_operator f_as(a1)))\ break;\ case e_tag__INTEGER:\ XEMMAI__CODE__BINARY_INTEGER(a_operator, )\ XEMMAI__CODE__BINARY_DERIVED_OR_THROW(a_operator, intptr_t, , .v_integer)\ break;\ - case e_tag__NULL:\ case e_tag__FLOAT:\ goto label__THROW_NOT_SUPPORTED;\ default:\ @@ -199,10 +196,8 @@ XEMMAI__CODE__CASE_BEGIN(a_name)\ switch (a0.f_tag()) {\ case e_tag__NULL:\ - XEMMAI__CODE__PRIMITIVE_CALL(a_operator(a1.f_tag() == e_tag__NULL))\ - break;\ - case e_tag__BOOLEAN:\ - XEMMAI__CODE__PRIMITIVE_CALL(a_operator(a1.f_tag() == e_tag__BOOLEAN && a0.v_boolean == a1.v_boolean))\ + case e_tag__TRUE:\ + XEMMAI__CODE__PRIMITIVE_CALL(a_operator(a0.f_tag() == a1.f_tag()))\ break;\ XEMMAI__CODE__BINARY_EQUALITY_PRIMITIVE(a_operator)\ default:\ diff --git a/src/global.cc b/src/global.cc index 7929c307..3489e389 100644 --- a/src/global.cc +++ b/src/global.cc @@ -23,7 +23,6 @@ void t_global::f_scan(t_scan a_scan) a_scan(v_type_advanced_lambda_shared); a_scan(v_type_method); a_scan(v_type_throwable); - a_scan(v_type_null); a_scan(v_type_boolean); a_scan(v_type_integer); a_scan(v_type_float); @@ -43,7 +42,6 @@ void t_global::f_scan(t_scan a_scan) a_scan(v_symbol_set_at); a_scan(v_symbol_plus); a_scan(v_symbol_minus); - a_scan(v_symbol_not); a_scan(v_symbol_complement); a_scan(v_symbol_multiply); a_scan(v_symbol_divide); @@ -80,7 +78,6 @@ std::vector> t_global::f_define() v_symbol_set_at = t_symbol::f_instantiate(L"__set_at"sv); v_symbol_plus = t_symbol::f_instantiate(L"__plus"sv); v_symbol_minus = t_symbol::f_instantiate(L"__minus"sv); - v_symbol_not = t_symbol::f_instantiate(L"__not"sv); v_symbol_complement = t_symbol::f_instantiate(L"__complement"sv); v_symbol_multiply = t_symbol::f_instantiate(L"__multiply"sv); v_symbol_divide = t_symbol::f_instantiate(L"__divide"sv); @@ -131,8 +128,6 @@ std::vector> t_global::f_define() v_type_method->v_builtin = true; t_type_of::f_define(); v_type_throwable->v_builtin = true; - t_type_of::f_define(); - v_type_null->v_builtin = true; t_type_of::f_define(); v_type_boolean->v_builtin = true; t_type_of::f_define(); @@ -166,7 +161,7 @@ std::vector> t_global::f_define() (L"Lambda"sv, static_cast(v_type_lambda)) (L"Method"sv, static_cast(v_type_method)) (L"Throwable"sv, static_cast(v_type_throwable)) - (L"Null"sv, static_cast(v_type_null)) + (L"Null"sv, static_cast(v_type_boolean)) (L"Boolean"sv, static_cast(v_type_boolean)) (L"Integer"sv, static_cast(v_type_integer)) (L"Float"sv, static_cast(v_type_float)) diff --git a/src/main.cc b/src/main.cc index 4cbc651b..cf80c925 100644 --- a/src/main.cc +++ b/src/main.cc @@ -189,8 +189,8 @@ class t_debugger : public xemmai::t_debugger case e_tag__NULL: std::fputs("null", v_out); break; - case e_tag__BOOLEAN: - std::fputs(f_as(a_value) ? "true" : "false", v_out); + case e_tag__TRUE: + std::fputs("true", v_out); break; case e_tag__INTEGER: std::fprintf(v_out, "%" PRIdPTR, f_as(a_value)); diff --git a/src/null.cc b/src/null.cc deleted file mode 100644 index 178af74d..00000000 --- a/src/null.cc +++ /dev/null @@ -1,13 +0,0 @@ -#include - -namespace xemmai -{ - -void t_type_of::f_define() -{ - t_define{f_global()} - (f_global()->f_symbol_string(), t_member()) - .f_derive(); -} - -} diff --git a/src/parser.cc b/src/parser.cc index e189a192..e9448315 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -36,7 +36,7 @@ std::unique_ptr t_parser::f_target(bool a_assignable) switch (v_lexer.f_token()) { case t_lexer::e_token__SYMBOL: { - t_object* symbol = f_symbol(); + auto symbol = f_symbol(); v_lexer.f_next(); if (v_lexer.f_token() == t_lexer::e_token__EQUAL) { if (!a_assignable) f_throw(L"can not assign to expression."sv); @@ -58,7 +58,7 @@ std::unique_ptr t_parser::f_target(bool a_assignable) v_lexer.f_next(); if (!v_lexer.f_newline() && v_lexer.f_token() == t_lexer::e_token__SYMBOL) { t_at at = v_lexer.f_at(); - t_object* key = f_symbol(); + auto key = f_symbol(); v_lexer.f_next(); if (v_lexer.f_token() == t_lexer::e_token__EQUAL) { if (!a_assignable) f_throw(L"can not assign to expression."sv); @@ -78,15 +78,15 @@ std::unique_ptr t_parser::f_target(bool a_assignable) switch (v_lexer.f_token()) { case t_lexer::e_token__SYMBOL: { - auto& symbol = f_symbol(); + auto symbol = f_symbol(); v_lexer.f_next(); - return std::make_unique>(at, symbol); + return std::make_unique>(at, symbol); } case t_lexer::e_token__LEFT_PARENTHESIS: { size_t indent = v_lexer.f_indent(); v_lexer.f_next(); - auto call = std::make_unique(at, std::make_unique>(at, v_module.f_slot(t_object::f_of(f_global()->f_type())))); + auto call = std::make_unique(at, std::make_unique>(at, v_module.f_slot(t_object::f_of(f_global()->f_type())))); if ((!v_lexer.f_newline() || v_lexer.f_indent() > indent) && v_lexer.f_token() != t_lexer::e_token__RIGHT_PARENTHESIS) call->v_expand = f_expressions(indent, call->v_arguments); if ((!v_lexer.f_newline() || v_lexer.f_indent() >= indent) && v_lexer.f_token() == t_lexer::e_token__RIGHT_PARENTHESIS) v_lexer.f_next(); return call; @@ -193,7 +193,7 @@ std::unique_ptr t_parser::f_target(bool a_assignable) { size_t indent = v_lexer.f_indent(); v_lexer.f_next(); - auto call = std::make_unique(at, std::make_unique>(at, v_module.f_slot(t_object::f_of(f_global()->f_type())))); + auto call = std::make_unique(at, std::make_unique>(at, v_module.f_slot(t_object::f_of(f_global()->f_type())))); if ((!v_lexer.f_newline() || v_lexer.f_indent() > indent) && v_lexer.f_token() != t_lexer::e_token__RIGHT_BRACKET) call->v_expand = f_expressions(indent, call->v_arguments); if ((!v_lexer.f_newline() || v_lexer.f_indent() >= indent) && v_lexer.f_token() == t_lexer::e_token__RIGHT_BRACKET) v_lexer.f_next(); return call; @@ -202,7 +202,7 @@ std::unique_ptr t_parser::f_target(bool a_assignable) { size_t indent = v_lexer.f_indent(); v_lexer.f_next(); - auto call = std::make_unique(at, std::make_unique>(at, v_module.f_slot(t_object::f_of(f_global()->f_type())))); + auto call = std::make_unique(at, std::make_unique>(at, v_module.f_slot(t_object::f_of(f_global()->f_type())))); if ((!v_lexer.f_newline() || v_lexer.f_indent() > indent) && v_lexer.f_token() != t_lexer::e_token__RIGHT_BRACE) while (true) { call->v_arguments.push_back(f_expression()); @@ -220,14 +220,12 @@ std::unique_ptr t_parser::f_target(bool a_assignable) return call; } case t_lexer::e_token__NULL: + case t_lexer::e_token__FALSE: v_lexer.f_next(); return std::make_unique(at); case t_lexer::e_token__TRUE: v_lexer.f_next(); - return std::make_unique>(at, true); - case t_lexer::e_token__FALSE: - v_lexer.f_next(); - return std::make_unique>(at, false); + return std::make_unique(at, true); case t_lexer::e_token__INTEGER: { auto value = v_lexer.f_integer(); @@ -244,7 +242,7 @@ std::unique_ptr t_parser::f_target(bool a_assignable) { auto value = v_lexer.f_string(); v_lexer.f_next(); - return std::make_unique>(at, v_module.f_slot(value)); + return std::make_unique>(at, v_module.f_slot(value)); } case t_lexer::e_token__BREAK: { @@ -314,7 +312,7 @@ std::unique_ptr t_parser::f_action(size_t a_indent, std::unique_ptr } case t_lexer::e_token__SYMBOL: { - t_object* key = f_symbol(); + auto key = f_symbol(); v_lexer.f_next(); if (v_lexer.f_token() == t_lexer::e_token__EQUAL) { if (!a_assignable) f_throw(L"can not assign to expression."sv); @@ -346,7 +344,7 @@ std::unique_ptr t_parser::f_action(size_t a_indent, std::unique_ptr } case t_lexer::e_token__SYMBOL: { - t_object* key = f_symbol(); + auto key = f_symbol(); v_lexer.f_next(); a_target.reset(new ast::t_object_has(at, std::move(a_target), key)); continue; @@ -594,9 +592,8 @@ std::unique_ptr t_parser::f_and_also(bool a_assignable) while (!v_lexer.f_newline() && v_lexer.f_token() == t_lexer::e_token__AND_ALSO) { t_at at = v_lexer.f_at(); v_lexer.f_next(); - auto branch = std::make_unique(at, std::move(node)); + auto branch = std::make_unique(at, std::move(node), true); branch->v_true.push_back(f_or(false)); - branch->v_false.emplace_back(new ast::t_literal(at, false)); node = std::move(branch); } return node; @@ -608,8 +605,7 @@ std::unique_ptr t_parser::f_or_else(bool a_assignable) while (!v_lexer.f_newline() && v_lexer.f_token() == t_lexer::e_token__OR_ELSE) { t_at at = v_lexer.f_at(); v_lexer.f_next(); - auto branch = std::make_unique(at, std::move(node)); - branch->v_true.emplace_back(new ast::t_literal(at, true)); + auto branch = std::make_unique(at, std::move(node), true); branch->v_false.push_back(f_and_also(false)); node = std::move(branch); } @@ -711,7 +707,7 @@ std::unique_ptr t_parser::f_expression() v_lexer.f_next(); auto expression = f_expression(); if (v_lexer.f_token() != t_lexer::e_token__SYMBOL) f_throw(L"expecting symbol."sv); - t_object* symbol = f_symbol(); + auto symbol = f_symbol(); v_lexer.f_next(); auto c = std::make_unique(std::move(expression), f_variable(v_scope, symbol)); f_block_or_expression(indent, c->v_block); diff --git a/src/type.cc b/src/type.cc index 71246cee..b7bb8751 100644 --- a/src/type.cc +++ b/src/type.cc @@ -32,7 +32,6 @@ void t_type::f_define() (f_global()->f_symbol_set_at(), f_not_supported) (f_global()->f_symbol_plus(), f_not_supported) (f_global()->f_symbol_minus(), f_not_supported) - (f_global()->f_symbol_not(), f_not_supported) (f_global()->f_symbol_complement(), f_not_supported) (f_global()->f_symbol_multiply(), f_not_supported) (f_global()->f_symbol_divide(), f_not_supported) @@ -47,9 +46,9 @@ void t_type::f_define() (f_global()->f_symbol_greater_equal(), f_not_supported) (f_global()->f_symbol_equals(), t_member()) (f_global()->f_symbol_not_equals(), t_member()) - (f_global()->f_symbol_and(), f_not_supported) - (f_global()->f_symbol_xor(), f_not_supported) - (f_global()->f_symbol_or(), f_not_supported) + (f_global()->f_symbol_and(), t_member()) + (f_global()->f_symbol_xor(), t_member()) + (f_global()->f_symbol_or(), t_member()) .f_derive(t_object::f_of(this)); } @@ -242,24 +241,23 @@ XEMMAI__TYPE__METHOD(get_at, 4, 1) XEMMAI__TYPE__METHOD(set_at, 5, 2) XEMMAI__TYPE__METHOD(plus, 6, 0) XEMMAI__TYPE__METHOD(minus, 7, 0) -XEMMAI__TYPE__METHOD(not, 8, 0) -XEMMAI__TYPE__METHOD(complement, 9, 0) -XEMMAI__TYPE__METHOD(multiply, 10, 1) -XEMMAI__TYPE__METHOD(divide, 11, 1) -XEMMAI__TYPE__METHOD(modulus, 12, 1) -XEMMAI__TYPE__METHOD(add, 13, 1) -XEMMAI__TYPE__METHOD(subtract, 14, 1) -XEMMAI__TYPE__METHOD(left_shift, 15, 1) -XEMMAI__TYPE__METHOD(right_shift, 16, 1) -XEMMAI__TYPE__METHOD(less, 17, 1) -XEMMAI__TYPE__METHOD(less_equal, 18, 1) -XEMMAI__TYPE__METHOD(greater, 19, 1) -XEMMAI__TYPE__METHOD(greater_equal, 20, 1) -XEMMAI__TYPE__METHOD(equals, 21, 1) -XEMMAI__TYPE__METHOD(not_equals, 22, 1) -XEMMAI__TYPE__METHOD(and, 23, 1) -XEMMAI__TYPE__METHOD(xor, 24, 1) -XEMMAI__TYPE__METHOD(or, 25, 1) +XEMMAI__TYPE__METHOD(complement, 8, 0) +XEMMAI__TYPE__METHOD(multiply, 9, 1) +XEMMAI__TYPE__METHOD(divide, 10, 1) +XEMMAI__TYPE__METHOD(modulus, 11, 1) +XEMMAI__TYPE__METHOD(add, 12, 1) +XEMMAI__TYPE__METHOD(subtract, 13, 1) +XEMMAI__TYPE__METHOD(left_shift, 14, 1) +XEMMAI__TYPE__METHOD(right_shift, 15, 1) +XEMMAI__TYPE__METHOD(less, 16, 1) +XEMMAI__TYPE__METHOD(less_equal, 17, 1) +XEMMAI__TYPE__METHOD(greater, 18, 1) +XEMMAI__TYPE__METHOD(greater_equal, 19, 1) +XEMMAI__TYPE__METHOD(equals, 20, 1) +XEMMAI__TYPE__METHOD(not_equals, 21, 1) +XEMMAI__TYPE__METHOD(and, 22, 1) +XEMMAI__TYPE__METHOD(xor, 23, 1) +XEMMAI__TYPE__METHOD(or, 24, 1) void f_throw_type_error [[noreturn]] (const std::type_info& a_type, const wchar_t* a_name) { diff --git a/test/directory.xm b/test/directory.xm index 3ccd5fd0..6c429c12 100644 --- a/test/directory.xm +++ b/test/directory.xm @@ -5,7 +5,7 @@ assert = @(x) x || throw Throwable("Assertion failed." directory = os.Directory("" + os.Path(system.script) / ".." try - while (entry = directory.read()) !== null + while entry = directory.read() special = entry.permissions >> 9 owner = entry.permissions >> 6 & 7 group = entry.permissions >> 3 & 7 diff --git a/test/operators.xm b/test/operators.xm index c1ea3493..42fac66c 100644 --- a/test/operators.xm +++ b/test/operators.xm @@ -6,7 +6,6 @@ Foo = Object + @ $__set_at = @(x, y) "a[" + x + "] = " + y $__plus = @ "+a" $__minus = @ "-a" - $__not = @ "!a" $__complement = @ "~a" $__multiply = @(x) "a * " + x $__divide = @(x) "a / " + x @@ -31,7 +30,7 @@ assert(a["x"] == "a[x]" assert((a["x"] = "y") == "a[x] = y" assert(+a == "+a" assert(-a == "-a" -assert(!a == "!a" +assert(!a === null assert(~a == "~a" assert(a * "x" == "a * x" assert(a / "x" == "a / x" diff --git a/test/pair.xm b/test/pair.xm index f6125212..2a2d8b95 100644 --- a/test/pair.xm +++ b/test/pair.xm @@ -4,12 +4,12 @@ Pair = Object + @ $__initialize = @(first, second) $first = first $second = second - $__string = @ $second === null ? $first.__string() : $first.__string() + " " + $second + $__string = @ $second ? $first.__string() + " " + $second : $first.__string() List = Object + @ $list $__initialize = @ $list = null - $__string = @ $list === null ? "()" : "(" + $list + ")" + $__string = @ $list ? "(" + $list + ")" : "()" $push = @(value) $list = Pair(value, $list $pop = @ value = $list.first diff --git a/test/primitives.xm b/test/primitives.xm index 39d39ea5..c9013a03 100644 --- a/test/primitives.xm +++ b/test/primitives.xm @@ -2,6 +2,8 @@ system = Module("system" print = system.out.write_line assert = @(x) x || throw Throwable("Assertion failed." +assert(false === null + print("!false = " + !false assert(!false === true print("!true = " + !true @@ -125,7 +127,7 @@ foo = "foo" assert((false && foo) === false assert((true && foo) === foo assert((false || foo) === foo -assert((true || foo) === true +assert((foo || "bar") === foo print("+(0 + 1) = " + +(0 + 1) assert(+(0 + 1) == 1 @@ -219,7 +221,14 @@ assert(Bar(1.0).__equals(1.0) print("Bar(1.0).__equals(2.0) = " + Bar(1.0).__equals(2.0) assert(!Bar(1.0).__equals(2.0) +assert(!"" === false assert("" === "" assert("" + "" === "" assert(foo + "" === foo assert("" + foo === foo +assert((foo & false) === false +assert((foo & "") === true +assert((foo ^ false) === true +assert((foo ^ "") === false +assert((foo | false) === true +assert((foo | "") === true diff --git a/test/psmtp.xm b/test/psmtp.xm index 8bc87c28..cfa69b71 100644 --- a/test/psmtp.xm +++ b/test/psmtp.xm @@ -11,11 +11,11 @@ server = @(co, log) x = co("250 Hello " + hostname + "\n" continue if x.substring(0, 11) == "MAIL FROM: " - if sender === null + if sender + x = co("503 Sender already specified\n" + else sender = x.substring(11 x = co("250 Sender " + sender + "\n" - else - x = co("503 Sender already specified\n" continue if x.substring(0, 9) == "RCPT TO: " recipient = x.substring(9 @@ -23,12 +23,12 @@ server = @(co, log) x = co("250 Recipient " + recipient + "\n" continue if x == "DATA" - if sender === null + if !sender x = co("503 Sender not specified\n" else if recipients == "" x = co("503 Recipients not specified\n" else - mail = hostname === null ? "" : "\tReceived: from " + hostname + "\n" + mail = hostname ? "\tReceived: from " + hostname + "\n" : "" mail = mail + "\tFrom: " + sender + "\n" mail = mail + recipients mail = mail + "\t\n" diff --git a/test/ring.xm b/test/ring.xm index f65e3255..aba041e0 100644 --- a/test/ring.xm +++ b/test/ring.xm @@ -11,20 +11,20 @@ Ring = Object + @ $__initialize = @ $ring = null $__string = @ - if $ring === null - return "()" - else + if $ring return "(" + $string($ring.next) + ")" + else + return "()" $string = @(cell) cell === $ring && return cell.value.__string( return cell.value.__string() + " " + $string(cell.next) $push = @(value) cell = Cell(value - if $ring === null - cell.next = cell - else + if $ring cell.next = $ring.next $ring.next = cell + else + cell.next = cell $ring = cell $pop = @ cell = $ring.next