Skip to content

Commit

Permalink
Made values truthy or falsy.
Browse files Browse the repository at this point in the history
null and false are falsy, all the other values are truthy.
  • Loading branch information
shin1m committed Feb 22, 2024
1 parent 25a4222 commit 54ed1c0
Show file tree
Hide file tree
Showing 21 changed files with 90 additions and 94 deletions.
2 changes: 2 additions & 0 deletions doc/Literals.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ This page explains literals.

boolean: 'true' | 'false' ;

`null` and `false` are falsy. The other values are all truthy.

## Integer Literals

integer: digit+ ;
Expand Down
16 changes: 15 additions & 1 deletion doc/TermExpressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ See [PrimaryExpressions](PrimaryExpressions.md).

unary: ('+' | '-' | '!' | '~')* primary ;

Negate operator (`!`) returns `true` if the operand is falsy, returns `false` otherwise.

## Multiplicative Expressions

multiplicative: unary (('*' | '/' | '%') unary)* ;
Expand All @@ -26,13 +28,21 @@ See [PrimaryExpressions](PrimaryExpressions.md).

relational: shift (('<' | '>' | '<=' | '>=') shift)* ;

Relational, equality, and identity operators return either `true` or `false`.

## 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 both the operands are booleans, throws an exception otherwise.

## Xor Expressions

Expand All @@ -46,10 +56,14 @@ See [PrimaryExpressions](PrimaryExpressions.md).

and_also: or ('&&' or)* ;

Evaluates the left operand, returns it if it is falsy, 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.

## Conditional Expressions

conditional: or_else ('?' conditional ':' conditional)? ;
7 changes: 4 additions & 3 deletions include/xemmai/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,14 +163,15 @@ struct t_lambda : t_node, t_scope
struct t_if : t_node
{
std::unique_ptr<t_node> v_condition;
bool v_preserve;
std::vector<std::unique_ptr<t_node>> v_true;
std::vector<std::unique_ptr<t_node>> v_false;
t_block v_block_true;
t_block v_block_false;
t_block v_junction;
t_block v_block_exit;

t_if(const t_at& a_at, std::unique_ptr<t_node>&& a_condition) : t_node(a_at), v_condition(std::move(a_condition))
t_if(const t_at& a_at, std::unique_ptr<t_node>&& 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);
Expand Down Expand Up @@ -618,9 +619,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)
{
Expand Down
11 changes: 7 additions & 4 deletions include/xemmai/boolean.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#ifndef XEMMAI__BOOLEAN_H
#define XEMMAI__BOOLEAN_H

#include "object.h"
#include "string.h"

namespace xemmai
{
Expand All @@ -14,15 +14,18 @@ struct t_type_of<bool> : t_uninstantiatable<t_bears<bool>>
{
static bool f_as(auto&& a_object)
{
return a_object.f_boolean();
return a_object && (a_object.f_tag() != e_tag__BOOLEAN || a_object.f_boolean());
}
static bool f_is(t_object* a_object)
{
return reinterpret_cast<uintptr_t>(a_object) == e_tag__BOOLEAN;
return true;
}
};

XEMMAI__PUBLIC static t_object* f__string(bool a_self);
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;
Expand Down
2 changes: 1 addition & 1 deletion include/xemmai/class.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ struct t_type_of<t_type> : t_uninstantiatable<t_bears<t_type>>
f_finalize = f_do_scan;
v_get = static_cast<t_pvalue (t_type::*)(t_object*, t_object*, size_t&)>(&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);
Expand Down
16 changes: 0 additions & 16 deletions include/xemmai/fiber.h
Original file line number Diff line number Diff line change
Expand Up @@ -279,22 +279,6 @@ inline t_pvalue t_value<T_tag>::f_##a_name() const\
XEMMAI__VALUE__UNARY_ARITHMETIC(plus, )
XEMMAI__VALUE__UNARY_ARITHMETIC(minus, -)

template<typename T_tag>
inline t_pvalue t_value<T_tag>::f_not() const
{
auto p = static_cast<t_object*>(*this);
switch (reinterpret_cast<uintptr_t>(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<typename T_tag>
inline t_pvalue t_value<T_tag>::f_complement() const
{
Expand Down
9 changes: 2 additions & 7 deletions include/xemmai/global.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,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;
Expand Down Expand Up @@ -121,10 +120,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;
Expand Down Expand Up @@ -373,8 +368,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__BOOLEAN:\
f_check<bool>(a_value, L"argument0");\
return static_cast<bool>(v_boolean a_operator f_as<bool>(a_value));\
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__INTEGER:\
f_check<intptr_t>(a_value, L"argument0");\
return v_integer a_operator f_as<intptr_t>(a_value);\
Expand Down
6 changes: 1 addition & 5 deletions include/xemmai/type.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ struct t_type_of<t_object>

static XEMMAI__TYPE__IDS_MODIFIER std::array<t_type_id, 1> V_ids{f_type_id<t_object>()};
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)
{
Expand Down Expand Up @@ -230,8 +230,6 @@ struct t_type_of<t_object>
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);
Expand Down Expand Up @@ -279,7 +277,6 @@ struct t_type_of<t_object>
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;
Expand Down Expand Up @@ -400,7 +397,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;
Expand Down
12 changes: 11 additions & 1 deletion include/xemmai/value.h
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,17 @@ class t_value : public T_tag
t_value<t_pointer> f_set_at(const t_value<t_pointer>& a_index, const t_value<t_pointer>& a_value) const;
t_value<t_pointer> f_plus() const;
t_value<t_pointer> f_minus() const;
t_value<t_pointer> f_not() const;
t_value<t_pointer> f_not() const
{
switch (reinterpret_cast<uintptr_t>(f_tag())) {
case e_tag__NULL:
return true;
case e_tag__BOOLEAN:
return !v_boolean;
default:
return false;
}
}
t_value<t_pointer> f_complement() const;
t_value<t_pointer> f_multiply(const t_value<t_pointer>& a_value) const;
t_value<t_pointer> f_divide(const t_value<t_pointer>& a_value) const;
Expand Down
16 changes: 10 additions & 6 deletions src/ast.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ namespace ast
namespace
{

void f_emit_block(t_emit& a_emit, const std::vector<std::unique_ptr<t_node>>& a_nodes, bool a_tail, bool a_clear)
void f_emit_block(t_emit& a_emit, const std::vector<std::unique_ptr<t_node>>& 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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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<intptr_t>(v_at, operand.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear);
case e_instruction__MINUS_T:
return t_literal<intptr_t>(v_at, -operand.v_integer).f_emit(a_emit, a_tail, a_operand, a_clear);
case e_instruction__NOT_T:
return t_literal<bool>(v_at, false).f_emit(a_emit, a_tail, a_operand, a_clear);
case e_instruction__COMPLEMENT_T:
return t_literal<intptr_t>(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();
Expand All @@ -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<double>(v_at, operand.v_float).f_emit(a_emit, a_tail, a_operand, a_clear);
case e_instruction__MINUS_T:
return t_literal<double>(v_at, -operand.v_float).f_emit(a_emit, a_tail, a_operand, a_clear);
case e_instruction__NOT_T:
return t_literal<bool>(v_at, false).f_emit(a_emit, a_tail, a_operand, a_clear);
default:
f_throw(L"not supported."sv);
}
Expand Down Expand Up @@ -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<intptr_t>(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();
Expand Down
5 changes: 0 additions & 5 deletions src/boolean.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,6 @@
namespace xemmai
{

t_object* t_type_of<bool>::f__string(bool a_self)
{
return t_string::f_instantiate(a_self ? L"true"sv : L"false"sv);
}

void t_type_of<bool>::f_define()
{
t_define{f_global()}
Expand Down
4 changes: 1 addition & 3 deletions src/code_operator.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,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(!f_as<bool>(a0))
XEMMAI__CODE__CASE_END
XEMMAI__CODE__CASE_BEGIN(COMPLEMENT)
if (a0.f_tag() == e_tag__INTEGER) {
Expand Down
2 changes: 0 additions & 2 deletions src/global.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,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);
Expand Down Expand Up @@ -80,7 +79,6 @@ std::vector<std::pair<t_root, t_rvalue>> 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);
Expand Down
6 changes: 2 additions & 4 deletions src/parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -594,9 +594,8 @@ std::unique_ptr<ast::t_node> 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<ast::t_if>(at, std::move(node));
auto branch = std::make_unique<ast::t_if>(at, std::move(node), true);
branch->v_true.push_back(f_or(false));
branch->v_false.emplace_back(new ast::t_literal<bool>(at, false));
node = std::move(branch);
}
return node;
Expand All @@ -608,8 +607,7 @@ std::unique_ptr<ast::t_node> 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<ast::t_if>(at, std::move(node));
branch->v_true.emplace_back(new ast::t_literal<bool>(at, true));
auto branch = std::make_unique<ast::t_if>(at, std::move(node), true);
branch->v_false.push_back(f_and_also(false));
node = std::move(branch);
}
Expand Down
Loading

0 comments on commit 54ed1c0

Please sign in to comment.