Skip to content

Commit

Permalink
Unified null and false.
Browse files Browse the repository at this point in the history
  • Loading branch information
shin1m committed Feb 22, 2024
1 parent 54ed1c0 commit 1fb8502
Show file tree
Hide file tree
Showing 26 changed files with 141 additions and 233 deletions.
4 changes: 3 additions & 1 deletion doc/Literals.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion doc/StackUsage.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
NUL
|
|N
BOOLEAN
TRUE
|
|B
INTEGER
Expand Down
10 changes: 5 additions & 5 deletions doc/TermExpressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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

Expand All @@ -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

Expand All @@ -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

Expand Down
2 changes: 1 addition & 1 deletion doc/WalkThrough.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ This document walks through xemmai language.
"This is a string."
null
true
false
false # => null

## Variables

Expand Down
44 changes: 12 additions & 32 deletions include/xemmai/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<const t_pvalue*>(&a_value))
t_operand(t_object* a_value) : v_tag(e_tag__LITERAL), v_value(a_value)
{
}
t_operand() : v_tag(e_tag__TEMPORARY)
Expand Down Expand Up @@ -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<typename T>
struct t_literal : t_node
Expand Down Expand Up @@ -569,11 +564,6 @@ struct XEMMAI__LOCAL t_emit
v_code->v_instructions.push_back(reinterpret_cast<void*>(a_operand));
return *this;
}
t_emit& operator<<(bool a_operand)
{
v_code->v_instructions.push_back(reinterpret_cast<void*>(a_operand ? 1 : 0));
return *this;
}
t_emit& operator<<(double a_operand)
{
union
Expand All @@ -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<t_pvalue*>(&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)
Expand Down Expand Up @@ -637,11 +622,6 @@ struct XEMMAI__LOCAL t_emit
}
};

template<>
constexpr t_instruction t_emit::f_instruction_of<bool>()
{
return e_instruction__BOOLEAN;
}
template<>
constexpr t_instruction t_emit::f_instruction_of<intptr_t>()
{
Expand All @@ -663,7 +643,7 @@ t_operand t_literal<T>::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_instruction>(t_emit::f_instruction_of<T>() + e_instruction__RETURN_BOOLEAN - e_instruction__BOOLEAN) << v_value;
a_emit << static_cast<t_instruction>(t_emit::f_instruction_of<T>() + e_instruction__RETURN_NUL - e_instruction__NUL) << v_value;
} else {
a_emit << t_emit::f_instruction_of<T>() << a_emit.v_stack << v_value;
}
Expand Down
8 changes: 2 additions & 6 deletions include/xemmai/boolean.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ struct t_type_of<bool> : t_uninstantiatable<t_bears<bool>>
{
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)
{
Expand All @@ -24,11 +24,7 @@ struct t_type_of<bool> : t_uninstantiatable<t_bears<bool>>

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();

Expand Down
4 changes: 2 additions & 2 deletions include/xemmai/code.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions include/xemmai/fiber.h
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ inline t_pvalue t_value<T_tag>::f_##a_name() const\
auto p = static_cast<t_object*>(*this);\
switch (reinterpret_cast<uintptr_t>(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);\
Expand All @@ -287,7 +287,7 @@ inline t_pvalue t_value<T_tag>::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:
Expand Down
2 changes: 1 addition & 1 deletion include/xemmai/float.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ struct t_type_of<double> : t_derivable<t_bears<double>, t_derived_primitive<doub
if (!std::is_same_v<typename t_fundamental<T>::t_type, double>) return reinterpret_cast<uintptr_t>(a_object) >= e_tag__OBJECT && a_object->f_type()->f_derives<typename t_fundamental<T>::t_type>();
switch (reinterpret_cast<uintptr_t>(a_object)) {
case e_tag__NULL:
case e_tag__BOOLEAN:
case e_tag__TRUE:
return false;
case e_tag__INTEGER:
case e_tag__FLOAT:
Expand Down
25 changes: 9 additions & 16 deletions include/xemmai/global.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -39,7 +38,6 @@ class t_global : public t_library
t_slot_of<t_type> v_type_advanced_lambda_shared;
t_slot_of<t_type> v_type_method;
t_slot_of<t_type> v_type_throwable;
t_slot_of<t_type> v_type_null;
t_slot_of<t_type> v_type_boolean;
t_slot_of<t_type> v_type_integer;
t_slot_of<t_type> v_type_float;
Expand Down Expand Up @@ -216,7 +214,6 @@ XEMMAI__LIBRARY__TYPE_AS(t_global, t_advanced_lambda<t_lambda>, advanced_lambda)
XEMMAI__LIBRARY__TYPE_AS(t_global, t_advanced_lambda<t_lambda_shared>, 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)
Expand Down Expand Up @@ -244,8 +241,7 @@ XEMMAI__PORTABLE__ALWAYS_INLINE inline t_type* t_value<T_tag>::f_type() const
auto p = static_cast<t_object*>(*this);
switch (reinterpret_cast<uintptr_t>(p)) {
case e_tag__NULL:
return f_global()->f_type<std::nullptr_t>();
case e_tag__BOOLEAN:
case e_tag__TRUE:
return f_global()->f_type<bool>();
case e_tag__INTEGER:
return f_global()->f_type<intptr_t>();
Expand Down Expand Up @@ -281,9 +277,8 @@ inline t_pvalue t_value<T_tag>::f_##a_name() const\
auto p = static_cast<t_object*>(*this);\
switch (reinterpret_cast<uintptr_t>(p)) {\
case e_tag__NULL:\
return t_type_of<std::nullptr_t>::f__##a_name(*this);\
case e_tag__BOOLEAN:\
return t_type_of<bool>::f__##a_name(v_boolean);\
case e_tag__TRUE:\
return t_type_of<bool>::f__##a_name(*this);\
case e_tag__INTEGER:\
return t_type_of<intptr_t>::f__##a_name(v_integer);\
case e_tag__FLOAT:\
Expand Down Expand Up @@ -315,7 +310,7 @@ inline t_pvalue t_value<T_tag>::f_##a_name(const t_pvalue& a_value) const\
auto p = static_cast<t_object*>(*this);\
switch (reinterpret_cast<uintptr_t>(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<intptr_t>::f__##a_name(v_integer, a_value);\
Expand All @@ -336,7 +331,7 @@ inline t_pvalue t_value<T_tag>::f_##a_name(const t_pvalue& a_value) const\
f_check<intptr_t>(a_value, L"argument0");\
return static_cast<uintptr_t>(v_integer) a_operator f_as<intptr_t>(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:\
Expand All @@ -350,9 +345,8 @@ inline t_pvalue t_value<T_tag>::f_##a_name(const t_pvalue& a_value) const\
auto p = static_cast<t_object*>(*this);\
switch (reinterpret_cast<uintptr_t>(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<intptr_t>::f__##a_name(v_integer, a_value);\
case e_tag__FLOAT:\
Expand All @@ -367,13 +361,12 @@ inline t_pvalue t_value<T_tag>::f_##a_name(const t_pvalue& a_value) const\
{\
auto p = static_cast<t_object*>(*this);\
switch (reinterpret_cast<uintptr_t>(p)) {\
case e_tag__BOOLEAN:\
if (a_value.f_tag() != e_tag__BOOLEAN) [[unlikely]] f_throw_type_error<bool>(L"argument0");\
return v_boolean a_operator a_value.v_boolean;\
case e_tag__NULL:\
case e_tag__TRUE:\
return static_cast<bool>(static_cast<bool>(p) a_operator f_as<bool>(a_value));\
case e_tag__INTEGER:\
f_check<intptr_t>(a_value, L"argument0");\
return v_integer a_operator f_as<intptr_t>(a_value);\
case e_tag__NULL:\
case e_tag__FLOAT:\
f_throw(L"not supported."sv);\
default:\
Expand Down
2 changes: 1 addition & 1 deletion include/xemmai/integer.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ struct t_type_of<intptr_t> : t_derivable<t_bears<intptr_t>, 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:
Expand Down
7 changes: 3 additions & 4 deletions include/xemmai/module.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,19 @@ struct t_module
struct t_script : t_module::t_body
{
std::wstring v_path;
std::deque<t_svalue> v_slots;
std::deque<t_slot> 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;
}
};

Expand Down
23 changes: 0 additions & 23 deletions include/xemmai/null.h

This file was deleted.

2 changes: 1 addition & 1 deletion include/xemmai/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ struct t_type::t_cast<T*>
switch (reinterpret_cast<uintptr_t>(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;
Expand Down
Loading

0 comments on commit 1fb8502

Please sign in to comment.