diff --git a/doc/Literals.md b/doc/Literals.md index 4ba32589..a7ee42b4 100644 --- a/doc/Literals.md +++ b/doc/Literals.md @@ -16,7 +16,9 @@ This page explains literals. boolean: 'true' | 'false' ; -`null` and `false` are falsy. The other values are all truthy. +`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 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 f2396eea..87e3ca35 100644 --- a/doc/TermExpressions.md +++ b/doc/TermExpressions.md @@ -10,7 +10,7 @@ See [PrimaryExpressions](PrimaryExpressions.md). unary: ('+' | '-' | '!' | '~')* primary ; -Negate operator (`!`) returns `true` if the operand is falsy, returns `false` otherwise. +Negate operator (`!`) returns `true` if the operand is `false` (`null`), returns `false` (`null`) otherwise. ## Multiplicative Expressions @@ -28,7 +28,7 @@ Negate operator (`!`) returns `true` if the operand is falsy, returns `false` ot relational: shift (('<' | '>' | '<=' | '>=') shift)* ; -Relational, equality, and identity operators return either `true` or `false`. +Relational, equality, and identity operators return either `true` or `false` (`null`). ## Equality Expressions @@ -42,7 +42,7 @@ Relational, equality, and identity operators return either `true` or `false`. and: identity ('&' identity)* ; -Bitwise operators (`&`, `^`, and `|`) do bitwise operations if both the operands are integers, do boolean operations if both the operands are booleans, throws an exception otherwise. +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 @@ -56,13 +56,13 @@ Bitwise operators (`&`, `^`, and `|`) do bitwise operations if both the operands and_also: or ('&&' or)* ; -Evaluates the left operand, returns it if it is falsy, evaluates the right operand and returns it otherwise. +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 truthy, evaluates the right operand and returns it otherwise. +Evaluates the left operand, returns it if it is not `false` (`null`), evaluates the right operand and returns it otherwise. ## Conditional Expressions 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 2a536ad3..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) @@ -418,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 @@ -569,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 @@ -585,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) @@ -637,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() { @@ -663,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 4b264837..a2cf5b6d 100644 --- a/include/xemmai/boolean.h +++ b/include/xemmai/boolean.h @@ -14,7 +14,7 @@ struct t_type_of : t_uninstantiatable> { static bool f_as(auto&& a_object) { - return a_object && (a_object.f_tag() != e_tag__BOOLEAN || a_object.f_boolean()); + return a_object; } static bool f_is(t_object* a_object) { @@ -24,11 +24,7 @@ struct t_type_of : t_uninstantiatable> static t_object* f__string(bool a_self) { - return t_string::f_instantiate(a_self ? L"true"sv : L"false"sv); - } - static intptr_t f__hash(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/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 b3915da5..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);\ @@ -287,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 026d5011..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; @@ -216,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) @@ -244,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(); @@ -281,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:\ @@ -315,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);\ @@ -336,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:\ @@ -350,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:\ @@ -367,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:\ - if (a_value.f_tag() != e_tag__BOOLEAN) [[unlikely]] f_throw_type_error(L"argument0");\ - return v_boolean a_operator a_value.v_boolean;\ + 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/value.h b/include/xemmai/value.h index ba087d73..5a963e49 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: @@ -303,10 +300,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; @@ -342,17 +335,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 - { - switch (reinterpret_cast(f_tag())) { - case e_tag__NULL: - return true; - case e_tag__BOOLEAN: - return !v_boolean; - default: - return false; - } - } 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 eb4110ad..3bb24268 100644 --- a/src/ast.cc +++ b/src/ast.cc @@ -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 {}; @@ -833,7 +833,7 @@ t_operand t_unary::f_emit(t_emit& a_emit, bool a_tail, bool a_operand, bool a_cl 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_literal(v_at, false).f_emit(a_emit, a_tail, a_operand, a_clear); + 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: @@ -847,7 +847,7 @@ t_operand t_unary::f_emit(t_emit& a_emit, bool a_tail, bool a_operand, bool a_cl 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_literal(v_at, false).f_emit(a_emit, a_tail, a_operand, a_clear); + return t_null(v_at).f_emit(a_emit, a_tail, a_operand, a_clear); default: f_throw(L"not supported."sv); } @@ -870,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; @@ -912,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: @@ -946,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); } @@ -978,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); } @@ -1008,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); } @@ -1071,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; @@ -1085,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/code.cc b/src/code.cc index fb58a803..7bef267e 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, @@ -451,12 +451,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) @@ -485,7 +484,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; } @@ -493,8 +492,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)); @@ -506,7 +505,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)]); @@ -579,7 +578,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)]; @@ -589,7 +588,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()\ @@ -601,7 +600,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()\ @@ -614,21 +613,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);\ @@ -637,7 +636,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()\ @@ -655,7 +654,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 597909dc..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,7 +41,7 @@ XEMMAI__CODE__UNARY_ARITHMETIC(PLUS, , f_plus) XEMMAI__CODE__UNARY_ARITHMETIC(MINUS, -, f_minus) XEMMAI__CODE__CASE_BEGIN(NOT) - XEMMAI__CODE__PRIMITIVE_CALL(!f_as(a0)) + XEMMAI__CODE__PRIMITIVE_CALL(!a0) XEMMAI__CODE__CASE_END XEMMAI__CODE__CASE_BEGIN(COMPLEMENT) if (a0.f_tag() == e_tag__INTEGER) { @@ -101,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 @@ -145,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)\ @@ -178,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:\ @@ -197,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 919a7906..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); @@ -129,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(); @@ -164,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 8b8c70f6..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; @@ -709,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/test/operators.xm b/test/operators.xm index 13084713..42fac66c 100644 --- a/test/operators.xm +++ b/test/operators.xm @@ -30,7 +30,7 @@ assert(a["x"] == "a[x]" assert((a["x"] = "y") == "a[x] = y" assert(+a == "+a" assert(-a == "-a" -assert(!a === false +assert(!a === null assert(~a == "~a" assert(a * "x" == "a * x" assert(a / "x" == "a / x" diff --git a/test/primitives.xm b/test/primitives.xm index 7f9a745a..93264e91 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