Skip to content

Commit

Permalink
Record binary comparison operators
Browse files Browse the repository at this point in the history
  • Loading branch information
electroly committed Jun 11, 2024
1 parent b81e4a3 commit 996b6dd
Show file tree
Hide file tree
Showing 12 changed files with 164 additions and 4 deletions.
10 changes: 9 additions & 1 deletion src/compiler/emit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -701,7 +701,7 @@ static void emitBinaryExpression(const BinaryExpressionNode& expressionNode, Pro
} else {
throw std::runtime_error("not impl");
}
} else if (lhsType->kind == Kind::kMap && lhsType->equals(*rhsType)) {
} else if (lhsType->kind == Kind::kMap && rhsType->kind == Kind::kMap) {
auto isFromValue = lhsType->mapKeyType->isValueType();
auto isToValue = lhsType->mapValueType->isValueType();
if (binarySuffix->binaryOperator == BinaryOperator::kAdd) {
Expand Down Expand Up @@ -735,6 +735,14 @@ static void emitBinaryExpression(const BinaryExpressionNode& expressionNode, Pro
} else {
throw std::runtime_error("not impl");
}
} else if (lhsType->kind == Kind::kRecord && rhsType->kind == Kind::kRecord) {
if (binarySuffix->binaryOperator == BinaryOperator::kEquals) {
state->syscall(Opcode::kSystemCallV, SystemCall::kRecordEquals, 0, 2);
} else if (binarySuffix->binaryOperator == BinaryOperator::kNotEquals) {
state->syscall(Opcode::kSystemCallV, SystemCall::kRecordNotEquals, 0, 2);
} else {
throw std::runtime_error("not impl");
}
} else {
throw std::runtime_error("not impl");
}
Expand Down
33 changes: 30 additions & 3 deletions src/compiler/typeCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -433,20 +433,47 @@ static void typeCheckBinaryExpression(BinaryExpressionNode* expressionNode, Type

case BinaryOperator::kEquals:
case BinaryOperator::kNotEquals:
if (!lhsType->equals(*rhsType)) {
throw CompilerException(
CompilerErrorCode::kTypeMismatch,
fmt::format(
"The \"{}\" operator requires the operands to have identical types.",
getOperatorText(suffix->binaryOperator)),
suffix->token);
}
lhsType = state->typeBoolean;
break;

case BinaryOperator::kLessThan:
case BinaryOperator::kLessThanEquals:
case BinaryOperator::kGreaterThan:
case BinaryOperator::kGreaterThanEquals: {
if (lhsType->equals(*rhsType)) {
suffix->evaluatedType = boost::make_local_shared<TypeNode>(Kind::kBoolean, suffix->token);
} else {
if (!lhsType->equals(*rhsType)) {
throw CompilerException(
CompilerErrorCode::kTypeMismatch,
fmt::format(
"The \"{}\" operator requires the operands to have identical types.",
getOperatorText(suffix->binaryOperator)),
suffix->token);
}
switch (lhsType->kind) {
case Kind::kDate:
case Kind::kDateTime:
case Kind::kDateTimeOffset:
case Kind::kNumber:
case Kind::kString:
case Kind::kTimeSpan:
suffix->evaluatedType = boost::make_local_shared<TypeNode>(Kind::kBoolean, suffix->token);
break;

default:
throw CompilerException(
CompilerErrorCode::kTypeMismatch,
fmt::format(
"The \"{}\" operator does not support the type \"{}\".",
getOperatorText(suffix->binaryOperator), lhsType->toString()),
suffix->token);
}
lhsType = state->typeBoolean;
break;
}
Expand Down
2 changes: 2 additions & 0 deletions src/shared/SystemCalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ enum class SystemCall {
kReadFileBytes,
kReadFileLines,
kReadFileText,
kRecordEquals,
kRecordNotEquals,
kRgb,
kRound,
kRunForm,
Expand Down
6 changes: 6 additions & 0 deletions src/test/CompilerTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,12 @@ COMPILER_TEST(records, anonymous_to_named_record_conversion_outside_block)
COMPILER_TEST(records, list_of_named_record_explicit_conversion)
COMPILER_TEST(records, named_record_type_1)
COMPILER_TEST(records, named_record_type_2)
COMPILER_TEST(records, record_comparison_equals)
COMPILER_TEST(records, record_comparison_greater_than)
COMPILER_TEST(records, record_comparison_greater_than_equals)
COMPILER_TEST(records, record_comparison_less_than)
COMPILER_TEST(records, record_comparison_less_than_equals)
COMPILER_TEST(records, record_comparison_not_equals)
COMPILER_TEST(records, record_default)
COMPILER_TEST(records, record_field_get_1)
COMPILER_TEST(records, record_field_get_2)
Expand Down
12 changes: 12 additions & 0 deletions src/test/programs/records/record_comparison_equals.bas
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
type Foo
Bar as Number
end type

sub Main()
dim a as Foo
dim b as Foo
if a = b then print "ok"
end sub

--output--
ok
16 changes: 16 additions & 0 deletions src/test/programs/records/record_comparison_greater_than.bas
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
type Foo
Bar as Number
end type

sub Main()
dim a as Foo
dim b as Foo
if a > b then print "wrong"
end sub

--output--
Compiler error
kTypeMismatch
Main
4:10
The ">" operator does not support the type "Foo".
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
type Foo
Bar as Number
end type

sub Main()
dim a as Foo
dim b as Foo
if a >= b then print "wrong"
end sub

--output--
Compiler error
kTypeMismatch
Main
4:10
The ">=" operator does not support the type "Foo".
16 changes: 16 additions & 0 deletions src/test/programs/records/record_comparison_less_than.bas
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
type Foo
Bar as Number
end type

sub Main()
dim a as Foo
dim b as Foo
if a < b then print "wrong"
end sub

--output--
Compiler error
kTypeMismatch
Main
4:10
The "<" operator does not support the type "Foo".
16 changes: 16 additions & 0 deletions src/test/programs/records/record_comparison_less_than_equals.bas
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
type Foo
Bar as Number
end type

sub Main()
dim a as Foo
dim b as Foo
if a <= b then print "wrong"
end sub

--output--
Compiler error
kTypeMismatch
Main
4:10
The "<=" operator does not support the type "Foo".
16 changes: 16 additions & 0 deletions src/test/programs/records/record_comparison_not_equals.bas
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
type Foo
Bar as Number
end type

sub Main()
dim a as Foo
dim b as Foo
if a <> b then
print "wrong"
else
print "ok"
end if
end sub

--output--
ok
4 changes: 4 additions & 0 deletions src/vm/initSystemCalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ void systemCallPrintString(const SystemCallInput&, SystemCallResult*);
void systemCallReadFileBytes(const SystemCallInput&, SystemCallResult*);
void systemCallReadFileLines(const SystemCallInput&, SystemCallResult*);
void systemCallReadFileText(const SystemCallInput&, SystemCallResult*);
void systemCallRecordEquals(const SystemCallInput&, SystemCallResult*);
void systemCallRecordNotEquals(const SystemCallInput&, SystemCallResult*);
void systemCallRgb(const SystemCallInput&, SystemCallResult*);
void systemCallRound(const SystemCallInput&, SystemCallResult*);
void systemCallRunForm(const SystemCallInput&, SystemCallResult*);
Expand Down Expand Up @@ -446,6 +448,8 @@ void initSystemCalls() {
initSystemCall(shared::SystemCall::kReadFileBytes, systemCallReadFileBytes);
initSystemCall(shared::SystemCall::kReadFileLines, systemCallReadFileLines);
initSystemCall(shared::SystemCall::kReadFileText, systemCallReadFileText);
initSystemCall(shared::SystemCall::kRecordEquals, systemCallRecordEquals);
initSystemCall(shared::SystemCall::kRecordNotEquals, systemCallRecordNotEquals);
initSystemCall(shared::SystemCall::kRgb, systemCallRgb);
initSystemCall(shared::SystemCall::kRound, systemCallRound);
initSystemCall(shared::SystemCall::kRunForm, systemCallRunForm);
Expand Down
21 changes: 21 additions & 0 deletions src/vm/systemCalls.records.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include "vm/systemCall.h"
#include "vm/castObject.h"
#include "vm/Record.h"

namespace vm {

// (lhs as Record, rhs as Record) as Boolean
void systemCallRecordEquals(const SystemCallInput& input, SystemCallResult* result) {
const auto& lhs = *castRecord(input.getObject(-2));
const auto& rhs = *castRecord(input.getObject(-1));
result->returnedValue = Value{ lhs.equals(rhs) };
}

// (lhs as Record, rhs as Record) as Boolean
void systemCallRecordNotEquals(const SystemCallInput& input, SystemCallResult* result) {
const auto& lhs = *castRecord(input.getObject(-2));
const auto& rhs = *castRecord(input.getObject(-1));
result->returnedValue = Value{ !lhs.equals(rhs) };
}

} // namespace vm

0 comments on commit 996b6dd

Please sign in to comment.