mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 14:54:07 +10:00
@@ -1,22 +1,38 @@
|
|||||||
|
|
||||||
//normal scope stuff
|
|
||||||
var answer = 42;
|
|
||||||
print answer;
|
|
||||||
|
|
||||||
{
|
print 1 == 1; //true
|
||||||
var answer = 7;
|
print 1 != 1; //false
|
||||||
print answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
print answer;
|
print 1 < 2; //true
|
||||||
|
|
||||||
//I wonder if...
|
print "foo" > "bar"; //true
|
||||||
var question = 42;
|
|
||||||
print question;
|
|
||||||
|
|
||||||
{
|
|
||||||
var question = question;
|
|
||||||
print question;
|
|
||||||
}
|
|
||||||
|
|
||||||
print question;
|
print 1 < 2; //true
|
||||||
|
print 1 > 2; //false
|
||||||
|
|
||||||
|
print 2 <= 2; //true
|
||||||
|
print 2 >= 2; //true
|
||||||
|
|
||||||
|
print 1 <= 2; //true
|
||||||
|
print 1 >= 2; //false
|
||||||
|
|
||||||
|
print true && true; //true
|
||||||
|
print true && false; //false
|
||||||
|
print false && true; //false
|
||||||
|
print false && false; //false
|
||||||
|
|
||||||
|
print true || true; //true
|
||||||
|
print true || false; //true
|
||||||
|
print false || true; //true
|
||||||
|
print false || false; //false
|
||||||
|
|
||||||
|
print !true; //false
|
||||||
|
print !false; //true
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//nesting
|
||||||
|
print true && false || true; //TODO: a warning is needed for this
|
||||||
@@ -199,8 +199,8 @@ static ParsingTuple parsingRulesetTable[] = {
|
|||||||
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_BRACE_RIGHT,
|
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_BRACE_RIGHT,
|
||||||
|
|
||||||
//other operators
|
//other operators
|
||||||
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_AND,
|
{PREC_AND,NULL,binary},// TOY_TOKEN_OPERATOR_AND,
|
||||||
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_OR,
|
{PREC_OR,NULL,binary},// TOY_TOKEN_OPERATOR_OR,
|
||||||
{PREC_NONE,unary,NULL},// TOY_TOKEN_OPERATOR_NEGATE,
|
{PREC_NONE,unary,NULL},// TOY_TOKEN_OPERATOR_NEGATE,
|
||||||
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_QUESTION,
|
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_QUESTION,
|
||||||
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_COLON,
|
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_COLON,
|
||||||
@@ -472,6 +472,17 @@ static Toy_AstFlag binary(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast
|
|||||||
return TOY_AST_FLAG_COMPARE_GREATER_EQUAL;
|
return TOY_AST_FLAG_COMPARE_GREATER_EQUAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//logical
|
||||||
|
case TOY_TOKEN_OPERATOR_AND: {
|
||||||
|
parsePrecedence(bucketHandle, parser, rootHandle, PREC_AND + 1);
|
||||||
|
return TOY_AST_FLAG_AND;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOY_TOKEN_OPERATOR_OR: {
|
||||||
|
parsePrecedence(bucketHandle, parser, rootHandle, PREC_OR + 1);
|
||||||
|
return TOY_AST_FLAG_OR;
|
||||||
|
}
|
||||||
|
|
||||||
case TOY_TOKEN_OPERATOR_CONCAT: {
|
case TOY_TOKEN_OPERATOR_CONCAT: {
|
||||||
parsePrecedence(bucketHandle, parser, rootHandle, PREC_CALL + 1);
|
parsePrecedence(bucketHandle, parser, rootHandle, PREC_CALL + 1);
|
||||||
return TOY_AST_FLAG_CONCAT;
|
return TOY_AST_FLAG_CONCAT;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ static void probeAndInsert(Toy_Table** tableHandle, Toy_Value key, Toy_Value val
|
|||||||
//probe
|
//probe
|
||||||
while (true) {
|
while (true) {
|
||||||
//if we're overriding an existing value
|
//if we're overriding an existing value
|
||||||
if (TOY_VALUES_ARE_EQUAL((*tableHandle)->data[probe].key, key)) {
|
if (Toy_checkValuesAreEqual((*tableHandle)->data[probe].key, key)) {
|
||||||
(*tableHandle)->data[probe] = entry;
|
(*tableHandle)->data[probe] = entry;
|
||||||
|
|
||||||
//TODO: benchmark the psl optimisation
|
//TODO: benchmark the psl optimisation
|
||||||
@@ -123,7 +123,7 @@ Toy_Value Toy_lookupTable(Toy_Table** tableHandle, Toy_Value key) {
|
|||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
//found the entry
|
//found the entry
|
||||||
if (TOY_VALUES_ARE_EQUAL((*tableHandle)->data[probe].key, key)) {
|
if (Toy_checkValuesAreEqual((*tableHandle)->data[probe].key, key)) {
|
||||||
return (*tableHandle)->data[probe].value;
|
return (*tableHandle)->data[probe].value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,7 +148,7 @@ void Toy_removeTable(Toy_Table** tableHandle, Toy_Value key) {
|
|||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
//found the entry
|
//found the entry
|
||||||
if (TOY_VALUES_ARE_EQUAL((*tableHandle)->data[probe].key, key)) {
|
if (Toy_checkValuesAreEqual((*tableHandle)->data[probe].key, key)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,78 +1,10 @@
|
|||||||
#include "toy_value.h"
|
#include "toy_value.h"
|
||||||
#include "toy_console_colors.h"
|
#include "toy_console_colors.h"
|
||||||
|
|
||||||
#include "toy_print.h"
|
|
||||||
#include "toy_string.h"
|
#include "toy_string.h"
|
||||||
|
#include "toy_print.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
//utils
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
bool Toy_private_isTruthy(Toy_Value value) {
|
|
||||||
//null is an error
|
|
||||||
if (TOY_VALUE_IS_NULL(value)) {
|
|
||||||
Toy_error(TOY_CC_ERROR "ERROR: 'null' is neither true nor false\n" TOY_CC_RESET);
|
|
||||||
}
|
|
||||||
|
|
||||||
//only 'false' is falsy
|
|
||||||
if (TOY_VALUE_IS_BOOLEAN(value)) {
|
|
||||||
return TOY_VALUE_AS_BOOLEAN(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
//anything else is truthy
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Toy_private_isEqual(Toy_Value left, Toy_Value right) {
|
|
||||||
//temp check
|
|
||||||
if (right.type > TOY_VALUE_STRING) {
|
|
||||||
Toy_error(TOY_CC_ERROR "ERROR: Unknown types in value equality comparison\n" TOY_CC_RESET);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(left.type) {
|
|
||||||
case TOY_VALUE_NULL:
|
|
||||||
return TOY_VALUE_IS_NULL(right);
|
|
||||||
|
|
||||||
case TOY_VALUE_BOOLEAN:
|
|
||||||
return TOY_VALUE_IS_BOOLEAN(right) && TOY_VALUE_AS_BOOLEAN(left) == TOY_VALUE_AS_BOOLEAN(right);
|
|
||||||
|
|
||||||
case TOY_VALUE_INTEGER:
|
|
||||||
if (TOY_VALUE_AS_INTEGER(right)) {
|
|
||||||
return TOY_VALUE_AS_INTEGER(left) == TOY_VALUE_AS_INTEGER(right);
|
|
||||||
}
|
|
||||||
if (TOY_VALUE_AS_FLOAT(right)) {
|
|
||||||
return TOY_VALUE_AS_INTEGER(left) == TOY_VALUE_AS_FLOAT(right);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case TOY_VALUE_FLOAT:
|
|
||||||
if (TOY_VALUE_AS_FLOAT(right)) {
|
|
||||||
return TOY_VALUE_AS_FLOAT(left) == TOY_VALUE_AS_FLOAT(right);
|
|
||||||
}
|
|
||||||
if (TOY_VALUE_AS_INTEGER(right)) {
|
|
||||||
return TOY_VALUE_AS_FLOAT(left) == TOY_VALUE_AS_INTEGER(right);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case TOY_VALUE_STRING:
|
|
||||||
if (TOY_VALUE_IS_STRING(right)) {
|
|
||||||
return Toy_compareStrings(TOY_VALUE_AS_STRING(left), TOY_VALUE_AS_STRING(right)) == 0;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case TOY_VALUE_ARRAY:
|
|
||||||
case TOY_VALUE_TABLE:
|
|
||||||
case TOY_VALUE_FUNCTION:
|
|
||||||
case TOY_VALUE_OPAQUE:
|
|
||||||
case TOY_VALUE_TYPE:
|
|
||||||
case TOY_VALUE_ANY:
|
|
||||||
case TOY_VALUE_UNKNOWN:
|
|
||||||
Toy_error(TOY_CC_ERROR "ERROR: Unknown types in value equality comparison\n" TOY_CC_RESET);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//hash util
|
|
||||||
static unsigned int hashUInt(unsigned int x) {
|
static unsigned int hashUInt(unsigned int x) {
|
||||||
x = ((x >> 16) ^ x) * 0x45d9f3b;
|
x = ((x >> 16) ^ x) * 0x45d9f3b;
|
||||||
x = ((x >> 16) ^ x) * 0x45d9f3b;
|
x = ((x >> 16) ^ x) * 0x45d9f3b;
|
||||||
@@ -80,6 +12,7 @@ static unsigned int hashUInt(unsigned int x) {
|
|||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//exposed functions
|
||||||
unsigned int Toy_hashValue(Toy_Value value) {
|
unsigned int Toy_hashValue(Toy_Value value) {
|
||||||
switch(value.type) {
|
switch(value.type) {
|
||||||
case TOY_VALUE_NULL:
|
case TOY_VALUE_NULL:
|
||||||
@@ -104,9 +37,10 @@ unsigned int Toy_hashValue(Toy_Value value) {
|
|||||||
case TOY_VALUE_TYPE:
|
case TOY_VALUE_TYPE:
|
||||||
case TOY_VALUE_ANY:
|
case TOY_VALUE_ANY:
|
||||||
case TOY_VALUE_UNKNOWN:
|
case TOY_VALUE_UNKNOWN:
|
||||||
Toy_error(TOY_CC_ERROR "ERROR: Can't hash an unknown type\n" TOY_CC_RESET);
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Toy_error(TOY_CC_ERROR "ERROR: Can't hash an unknown value type\n" TOY_CC_RESET);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,10 +64,11 @@ Toy_Value Toy_copyValue(Toy_Value value) {
|
|||||||
case TOY_VALUE_TYPE:
|
case TOY_VALUE_TYPE:
|
||||||
case TOY_VALUE_ANY:
|
case TOY_VALUE_ANY:
|
||||||
case TOY_VALUE_UNKNOWN:
|
case TOY_VALUE_UNKNOWN:
|
||||||
Toy_error(TOY_CC_ERROR "ERROR: Can't copy an unknown type\n" TOY_CC_RESET);
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//dummy return
|
//dummy return
|
||||||
|
Toy_error(TOY_CC_ERROR "ERROR: Can't copy an unknown value type\n" TOY_CC_RESET);
|
||||||
return TOY_VALUE_FROM_NULL();
|
return TOY_VALUE_FROM_NULL();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,3 +96,148 @@ void Toy_freeValue(Toy_Value value) {
|
|||||||
Toy_error(TOY_CC_ERROR "ERROR: Can't free an unknown type\n" TOY_CC_RESET);
|
Toy_error(TOY_CC_ERROR "ERROR: Can't free an unknown type\n" TOY_CC_RESET);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Toy_checkValueIsTruthy(Toy_Value value) {
|
||||||
|
//null is an error
|
||||||
|
if (TOY_VALUE_IS_NULL(value)) {
|
||||||
|
Toy_error(TOY_CC_ERROR "ERROR: 'null' is neither true nor false\n" TOY_CC_RESET);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//only 'false' is falsy
|
||||||
|
if (TOY_VALUE_IS_BOOLEAN(value)) {
|
||||||
|
return TOY_VALUE_AS_BOOLEAN(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
//anything else is truthy
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Toy_checkValuesAreEqual(Toy_Value left, Toy_Value right) {
|
||||||
|
switch(left.type) {
|
||||||
|
case TOY_VALUE_NULL:
|
||||||
|
return TOY_VALUE_IS_NULL(right);
|
||||||
|
|
||||||
|
case TOY_VALUE_BOOLEAN:
|
||||||
|
return TOY_VALUE_IS_BOOLEAN(right) && TOY_VALUE_AS_BOOLEAN(left) == TOY_VALUE_AS_BOOLEAN(right);
|
||||||
|
|
||||||
|
case TOY_VALUE_INTEGER:
|
||||||
|
if (TOY_VALUE_IS_INTEGER(right)) {
|
||||||
|
return TOY_VALUE_AS_INTEGER(left) == TOY_VALUE_AS_INTEGER(right);
|
||||||
|
}
|
||||||
|
else if (TOY_VALUE_IS_FLOAT(right)) {
|
||||||
|
return TOY_VALUE_AS_INTEGER(left) == TOY_VALUE_AS_FLOAT(right);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOY_VALUE_FLOAT:
|
||||||
|
if (TOY_VALUE_IS_INTEGER(right)) {
|
||||||
|
return TOY_VALUE_AS_FLOAT(left) == TOY_VALUE_AS_INTEGER(right);
|
||||||
|
}
|
||||||
|
else if (TOY_VALUE_IS_FLOAT(right)) {
|
||||||
|
return TOY_VALUE_AS_FLOAT(left) == TOY_VALUE_AS_FLOAT(right);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOY_VALUE_STRING:
|
||||||
|
if (TOY_VALUE_IS_STRING(right)) {
|
||||||
|
return Toy_compareStrings(TOY_VALUE_AS_STRING(left), TOY_VALUE_AS_STRING(right)) == 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOY_VALUE_ARRAY:
|
||||||
|
case TOY_VALUE_TABLE:
|
||||||
|
case TOY_VALUE_FUNCTION:
|
||||||
|
case TOY_VALUE_OPAQUE:
|
||||||
|
case TOY_VALUE_TYPE:
|
||||||
|
case TOY_VALUE_ANY:
|
||||||
|
case TOY_VALUE_UNKNOWN:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_error(TOY_CC_ERROR "ERROR: Unknown types in value equality\n" TOY_CC_RESET);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Toy_checkValuesAreComparable(Toy_Value left, Toy_Value right) {
|
||||||
|
switch(left.type) {
|
||||||
|
case TOY_VALUE_NULL:
|
||||||
|
return false;
|
||||||
|
|
||||||
|
case TOY_VALUE_BOOLEAN:
|
||||||
|
return TOY_VALUE_IS_BOOLEAN(right);
|
||||||
|
|
||||||
|
case TOY_VALUE_INTEGER:
|
||||||
|
case TOY_VALUE_FLOAT:
|
||||||
|
return TOY_VALUE_IS_INTEGER(right) || TOY_VALUE_IS_FLOAT(right);
|
||||||
|
|
||||||
|
case TOY_VALUE_STRING:
|
||||||
|
return TOY_VALUE_IS_STRING(right);
|
||||||
|
|
||||||
|
case TOY_VALUE_ARRAY:
|
||||||
|
case TOY_VALUE_TABLE:
|
||||||
|
case TOY_VALUE_FUNCTION:
|
||||||
|
case TOY_VALUE_OPAQUE:
|
||||||
|
case TOY_VALUE_TYPE:
|
||||||
|
case TOY_VALUE_ANY:
|
||||||
|
case TOY_VALUE_UNKNOWN:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_error(TOY_CC_ERROR "ERROR: Unknown types in value comparison check\n" TOY_CC_RESET);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Toy_compareValues(Toy_Value left, Toy_Value right) {
|
||||||
|
//comparison means there's a difference in value, with some kind of quantity - so null, bool, etc. aren't comparable
|
||||||
|
switch(left.type) {
|
||||||
|
case TOY_VALUE_NULL:
|
||||||
|
case TOY_VALUE_BOOLEAN:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TOY_VALUE_INTEGER:
|
||||||
|
if (TOY_VALUE_IS_INTEGER(right)) {
|
||||||
|
return TOY_VALUE_AS_INTEGER(left) - TOY_VALUE_AS_INTEGER(right);
|
||||||
|
}
|
||||||
|
else if (TOY_VALUE_IS_FLOAT(right)) {
|
||||||
|
return TOY_VALUE_AS_INTEGER(left) - TOY_VALUE_AS_FLOAT(right);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOY_VALUE_FLOAT:
|
||||||
|
if (TOY_VALUE_IS_INTEGER(right)) {
|
||||||
|
return TOY_VALUE_AS_FLOAT(left) - TOY_VALUE_AS_INTEGER(right);
|
||||||
|
}
|
||||||
|
else if (TOY_VALUE_IS_FLOAT(right)) {
|
||||||
|
return TOY_VALUE_AS_FLOAT(left) - TOY_VALUE_AS_FLOAT(right);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOY_VALUE_STRING:
|
||||||
|
if (TOY_VALUE_IS_STRING(right)) {
|
||||||
|
return Toy_compareStrings(TOY_VALUE_AS_STRING(left), TOY_VALUE_AS_STRING(right));
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOY_VALUE_ARRAY:
|
||||||
|
case TOY_VALUE_TABLE:
|
||||||
|
case TOY_VALUE_FUNCTION:
|
||||||
|
case TOY_VALUE_OPAQUE:
|
||||||
|
case TOY_VALUE_TYPE:
|
||||||
|
case TOY_VALUE_ANY:
|
||||||
|
case TOY_VALUE_UNKNOWN:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_error(TOY_CC_ERROR "ERROR: Unknown types in value comparison\n" TOY_CC_RESET);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|||||||
@@ -57,13 +57,13 @@ typedef struct Toy_Value { //32 | 64 BITNESS
|
|||||||
#define TOY_VALUE_FROM_STRING(value) ((Toy_Value){{ .string = value }, TOY_VALUE_STRING})
|
#define TOY_VALUE_FROM_STRING(value) ((Toy_Value){{ .string = value }, TOY_VALUE_STRING})
|
||||||
//TODO: more
|
//TODO: more
|
||||||
|
|
||||||
#define TOY_VALUE_IS_TRUTHY(value) Toy_private_isTruthy(value)
|
//utilities
|
||||||
TOY_API bool Toy_private_isTruthy(Toy_Value value);
|
TOY_API unsigned int Toy_hashValue(Toy_Value value);
|
||||||
|
|
||||||
#define TOY_VALUES_ARE_EQUAL(left, right) Toy_private_isEqual(left, right)
|
|
||||||
TOY_API bool Toy_private_isEqual(Toy_Value left, Toy_Value right);
|
|
||||||
|
|
||||||
unsigned int Toy_hashValue(Toy_Value value);
|
|
||||||
|
|
||||||
TOY_API Toy_Value Toy_copyValue(Toy_Value value);
|
TOY_API Toy_Value Toy_copyValue(Toy_Value value);
|
||||||
TOY_API void Toy_freeValue(Toy_Value value);
|
TOY_API void Toy_freeValue(Toy_Value value);
|
||||||
|
|
||||||
|
TOY_API bool Toy_checkValueIsTruthy(Toy_Value value);
|
||||||
|
TOY_API bool Toy_checkValuesAreEqual(Toy_Value left, Toy_Value right);
|
||||||
|
TOY_API bool Toy_checkValuesAreComparable(Toy_Value left, Toy_Value right);
|
||||||
|
TOY_API int Toy_compareValues(Toy_Value left, Toy_Value right);
|
||||||
|
|||||||
@@ -194,6 +194,18 @@ static void processAccess(Toy_VM* vm) {
|
|||||||
Toy_freeValue(name);
|
Toy_freeValue(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void processDuplicate(Toy_VM* vm) {
|
||||||
|
Toy_Value value = Toy_copyValue(Toy_peekStack(&vm->stack));
|
||||||
|
Toy_pushStack(&vm->stack, value);
|
||||||
|
Toy_freeValue(value);
|
||||||
|
|
||||||
|
//check for compound assignments
|
||||||
|
Toy_OpcodeType squeezed = READ_BYTE(vm);
|
||||||
|
if (squeezed == TOY_OPCODE_ACCESS) {
|
||||||
|
processAccess(vm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void processArithmetic(Toy_VM* vm, Toy_OpcodeType opcode) {
|
static void processArithmetic(Toy_VM* vm, Toy_OpcodeType opcode) {
|
||||||
Toy_Value right = Toy_popStack(&vm->stack);
|
Toy_Value right = Toy_popStack(&vm->stack);
|
||||||
Toy_Value left = Toy_popStack(&vm->stack);
|
Toy_Value left = Toy_popStack(&vm->stack);
|
||||||
@@ -214,7 +226,7 @@ static void processArithmetic(Toy_VM* vm, Toy_OpcodeType opcode) {
|
|||||||
|
|
||||||
//check for modulo by a float
|
//check for modulo by a float
|
||||||
if (opcode == TOY_OPCODE_MODULO && TOY_VALUE_IS_FLOAT(right)) {
|
if (opcode == TOY_OPCODE_MODULO && TOY_VALUE_IS_FLOAT(right)) {
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Can't modulo by a float, exiting\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Can't modulo by a float, exiting\n" TOY_CC_RESET); //TODO: swap these with Toy_error so the repl doens't exit
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,25 +272,13 @@ static void processArithmetic(Toy_VM* vm, Toy_OpcodeType opcode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void processDuplicate(Toy_VM* vm) {
|
|
||||||
Toy_Value value = Toy_copyValue(Toy_peekStack(&vm->stack));
|
|
||||||
Toy_pushStack(&vm->stack, value);
|
|
||||||
Toy_freeValue(value);
|
|
||||||
|
|
||||||
//check for compound assignments
|
|
||||||
Toy_OpcodeType squeezed = READ_BYTE(vm);
|
|
||||||
if (squeezed == TOY_OPCODE_ACCESS) {
|
|
||||||
processAccess(vm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void processComparison(Toy_VM* vm, Toy_OpcodeType opcode) {
|
static void processComparison(Toy_VM* vm, Toy_OpcodeType opcode) {
|
||||||
Toy_Value right = Toy_popStack(&vm->stack);
|
Toy_Value right = Toy_popStack(&vm->stack);
|
||||||
Toy_Value left = Toy_popStack(&vm->stack);
|
Toy_Value left = Toy_popStack(&vm->stack);
|
||||||
|
|
||||||
//most things can be equal, so handle it separately
|
//most things can be equal, so handle it separately
|
||||||
if (opcode == TOY_OPCODE_COMPARE_EQUAL) {
|
if (opcode == TOY_OPCODE_COMPARE_EQUAL) {
|
||||||
bool equal = TOY_VALUES_ARE_EQUAL(left, right);
|
bool equal = Toy_checkValuesAreEqual(left, right);
|
||||||
|
|
||||||
//equality has an optional "negate" opcode within it's word
|
//equality has an optional "negate" opcode within it's word
|
||||||
if (READ_BYTE(vm) != TOY_OPCODE_NEGATE) {
|
if (READ_BYTE(vm) != TOY_OPCODE_NEGATE) {
|
||||||
@@ -291,31 +291,31 @@ static void processComparison(Toy_VM* vm, Toy_OpcodeType opcode) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//coerce ints into floats if needed
|
if (Toy_checkValuesAreComparable(left, right) == false) {
|
||||||
if (TOY_VALUE_IS_INTEGER(left) && TOY_VALUE_IS_FLOAT(right)) {
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Can't compare value types %d and %d\n" TOY_CC_RESET, left.type, right.type); //TODO: typeToCString for error messages
|
||||||
left = TOY_VALUE_FROM_FLOAT( (float)TOY_VALUE_AS_INTEGER(left) );
|
exit(-1);
|
||||||
}
|
|
||||||
else
|
|
||||||
if (TOY_VALUE_IS_FLOAT(left) && TOY_VALUE_IS_INTEGER(right)) {
|
|
||||||
right = TOY_VALUE_FROM_FLOAT( (float)TOY_VALUE_AS_INTEGER(right) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//other opcodes
|
//get the comparison
|
||||||
if (opcode == TOY_OPCODE_COMPARE_LESS) {
|
int comparison = Toy_compareValues(left, right);
|
||||||
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN(TOY_VALUE_IS_FLOAT(left) ? TOY_VALUE_AS_FLOAT(left) < TOY_VALUE_AS_FLOAT(right) : TOY_VALUE_AS_INTEGER(left) < TOY_VALUE_AS_INTEGER(right)) );
|
|
||||||
|
//push the result of the comparison as a boolean, based on the opcode
|
||||||
|
if (opcode == TOY_OPCODE_COMPARE_LESS && comparison < 0) {
|
||||||
|
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN(true));
|
||||||
}
|
}
|
||||||
else if (opcode == TOY_OPCODE_COMPARE_LESS_EQUAL) {
|
else if (opcode == TOY_OPCODE_COMPARE_LESS_EQUAL && (comparison < 0 || comparison == 0)) {
|
||||||
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN(TOY_VALUE_IS_FLOAT(left) ? TOY_VALUE_AS_FLOAT(left) <= TOY_VALUE_AS_FLOAT(right) : TOY_VALUE_AS_INTEGER(left) <= TOY_VALUE_AS_INTEGER(right)) );
|
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN(true));
|
||||||
}
|
}
|
||||||
else if (opcode == TOY_OPCODE_COMPARE_GREATER) {
|
else if (opcode == TOY_OPCODE_COMPARE_GREATER && comparison > 0) {
|
||||||
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN(TOY_VALUE_IS_FLOAT(left) ? TOY_VALUE_AS_FLOAT(left) > TOY_VALUE_AS_FLOAT(right) : TOY_VALUE_AS_INTEGER(left) > TOY_VALUE_AS_INTEGER(right)) );
|
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN(true));
|
||||||
}
|
}
|
||||||
else if (opcode == TOY_OPCODE_COMPARE_GREATER_EQUAL) {
|
else if (opcode == TOY_OPCODE_COMPARE_GREATER_EQUAL && (comparison > 0 || comparison == 0)) {
|
||||||
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN(TOY_VALUE_IS_FLOAT(left) ? TOY_VALUE_AS_FLOAT(left) >= TOY_VALUE_AS_FLOAT(right) : TOY_VALUE_AS_INTEGER(left) >= TOY_VALUE_AS_INTEGER(right)) );
|
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if all else failed, then it's not true
|
||||||
else {
|
else {
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Invalid opcode %d passed to processComparison, exiting\n" TOY_CC_RESET, opcode);
|
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN(false));
|
||||||
exit(-1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,23 +324,23 @@ static void processLogical(Toy_VM* vm, Toy_OpcodeType opcode) {
|
|||||||
Toy_Value right = Toy_popStack(&vm->stack);
|
Toy_Value right = Toy_popStack(&vm->stack);
|
||||||
Toy_Value left = Toy_popStack(&vm->stack);
|
Toy_Value left = Toy_popStack(&vm->stack);
|
||||||
|
|
||||||
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN( TOY_VALUE_IS_TRUTHY(left) && TOY_VALUE_IS_TRUTHY(right) ));
|
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN( Toy_checkValueIsTruthy(left) && Toy_checkValueIsTruthy(right) ));
|
||||||
}
|
}
|
||||||
else if (opcode == TOY_OPCODE_OR) {
|
else if (opcode == TOY_OPCODE_OR) {
|
||||||
Toy_Value right = Toy_popStack(&vm->stack);
|
Toy_Value right = Toy_popStack(&vm->stack);
|
||||||
Toy_Value left = Toy_popStack(&vm->stack);
|
Toy_Value left = Toy_popStack(&vm->stack);
|
||||||
|
|
||||||
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN( TOY_VALUE_IS_TRUTHY(left) || TOY_VALUE_IS_TRUTHY(right) ));
|
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN( Toy_checkValueIsTruthy(left) || Toy_checkValueIsTruthy(right) ));
|
||||||
}
|
}
|
||||||
else if (opcode == TOY_OPCODE_TRUTHY) {
|
else if (opcode == TOY_OPCODE_TRUTHY) {
|
||||||
Toy_Value top = Toy_popStack(&vm->stack);
|
Toy_Value top = Toy_popStack(&vm->stack);
|
||||||
|
|
||||||
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN( TOY_VALUE_IS_TRUTHY(top) ));
|
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN( Toy_checkValueIsTruthy(top) ));
|
||||||
}
|
}
|
||||||
else if (opcode == TOY_OPCODE_NEGATE) {
|
else if (opcode == TOY_OPCODE_NEGATE) {
|
||||||
Toy_Value top = Toy_popStack(&vm->stack);
|
Toy_Value top = Toy_popStack(&vm->stack); //bad values are filtered by the parser
|
||||||
|
|
||||||
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN( !TOY_VALUE_IS_TRUTHY(top) ));
|
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_BOOLEAN( !Toy_checkValueIsTruthy(top) ));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Invalid opcode %d passed to processLogical, exiting\n" TOY_CC_RESET, opcode);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Invalid opcode %d passed to processLogical, exiting\n" TOY_CC_RESET, opcode);
|
||||||
@@ -410,12 +410,7 @@ static void processConcat(Toy_VM* vm) {
|
|||||||
Toy_Value right = Toy_popStack(&vm->stack);
|
Toy_Value right = Toy_popStack(&vm->stack);
|
||||||
Toy_Value left = Toy_popStack(&vm->stack);
|
Toy_Value left = Toy_popStack(&vm->stack);
|
||||||
|
|
||||||
if (!TOY_VALUE_IS_STRING(left)) {
|
if (!TOY_VALUE_IS_STRING(left) || !TOY_VALUE_IS_STRING(right)) {
|
||||||
Toy_error("Failed to concatenate a value that is not a string");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!TOY_VALUE_IS_STRING(left)) {
|
|
||||||
Toy_error("Failed to concatenate a value that is not a string");
|
Toy_error("Failed to concatenate a value that is not a string");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,16 +5,18 @@
|
|||||||
#include "toy_string.h"
|
#include "toy_string.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
int main() {
|
int test_value_creation() {
|
||||||
//test for the correct size
|
//test for the correct size
|
||||||
{
|
{
|
||||||
#if TOY_BITNESS == 64
|
#if TOY_BITNESS == 64
|
||||||
if (sizeof(Toy_Value) != 16) {
|
if (sizeof(Toy_Value) != 16)
|
||||||
#else
|
#else
|
||||||
if (sizeof(Toy_Value) != 8) {
|
if (sizeof(Toy_Value) != 8)
|
||||||
#endif
|
#endif
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: 'Toy_Value' is an unexpected size in memory\n" TOY_CC_RESET);
|
{
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: 'Toy_Value' is an unexpected size in memory, expected %d found %d\n" TOY_CC_RESET, TOY_BITNESS, sizeof(Toy_Value));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -29,34 +31,147 @@ int main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//test creating values
|
//test creating booleans
|
||||||
{
|
{
|
||||||
Toy_Value t = TOY_VALUE_FROM_BOOLEAN(true);
|
Toy_Value t = TOY_VALUE_FROM_BOOLEAN(true);
|
||||||
Toy_Value f = TOY_VALUE_FROM_BOOLEAN(false);
|
Toy_Value f = TOY_VALUE_FROM_BOOLEAN(false);
|
||||||
|
|
||||||
if (!TOY_VALUE_IS_TRUTHY(t) || TOY_VALUE_IS_TRUTHY(f)) {
|
if (!Toy_checkValueIsTruthy(t) || Toy_checkValueIsTruthy(f)) {
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: 'boolean' value failed\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: 'boolean' value failed\n" TOY_CC_RESET);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//test creating strings
|
||||||
|
{
|
||||||
|
//setup
|
||||||
|
Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_SMALL);
|
||||||
|
|
||||||
|
Toy_Value greeting = TOY_VALUE_FROM_STRING(Toy_createString(&bucket, "Hello world!"));
|
||||||
|
|
||||||
|
if (TOY_VALUE_IS_STRING(greeting) == false ||
|
||||||
|
TOY_VALUE_AS_STRING(greeting)->type != TOY_STRING_LEAF ||
|
||||||
|
strcmp(TOY_VALUE_AS_STRING(greeting)->as.leaf.data, "Hello world!") != 0
|
||||||
|
)
|
||||||
|
{
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: 'string' value failed\n" TOY_CC_RESET);
|
||||||
|
Toy_freeBucket(&bucket);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
Toy_freeBucket(&bucket);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_value_equality() {
|
||||||
//test value equality
|
//test value equality
|
||||||
{
|
{
|
||||||
Toy_Value answer = TOY_VALUE_FROM_INTEGER(42);
|
Toy_Value answer = TOY_VALUE_FROM_INTEGER(42);
|
||||||
Toy_Value question = TOY_VALUE_FROM_INTEGER(42);
|
Toy_Value question = TOY_VALUE_FROM_INTEGER(42);
|
||||||
Toy_Value nice = TOY_VALUE_FROM_INTEGER(69);
|
Toy_Value nice = TOY_VALUE_FROM_INTEGER(69);
|
||||||
|
|
||||||
if (!TOY_VALUES_ARE_EQUAL(answer, question)) {
|
if (Toy_checkValuesAreEqual(answer, question) != true) {
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: equality check failed, expected true\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: value equality check failed, expected true\n" TOY_CC_RESET);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TOY_VALUES_ARE_EQUAL(answer, nice)) {
|
if (Toy_checkValuesAreEqual(answer, nice) != false) {
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: equality check failed, expected false\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: value equality check failed, expected false\n" TOY_CC_RESET);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//again with strings
|
||||||
|
{
|
||||||
|
//setup
|
||||||
|
Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_SMALL);
|
||||||
|
|
||||||
|
Toy_Value answer = TOY_VALUE_FROM_STRING(Toy_createString(&bucket, "poe wrote on both"));
|
||||||
|
Toy_Value question = TOY_VALUE_FROM_STRING(Toy_createString(&bucket, "why is a raven like a writing desk?"));
|
||||||
|
Toy_Value duplicate = TOY_VALUE_FROM_STRING(Toy_createString(&bucket, "poe wrote on both"));
|
||||||
|
|
||||||
|
if (Toy_checkValuesAreEqual(answer, duplicate) != true) {
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: string value equality check failed, expected true\n" TOY_CC_RESET);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Toy_checkValuesAreEqual(answer, question) != false) {
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: string value equality check failed, expected false\n" TOY_CC_RESET);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
Toy_freeBucket(&bucket);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_value_comparison() {
|
||||||
|
//test value comparable
|
||||||
|
{
|
||||||
|
Toy_Value answer = TOY_VALUE_FROM_INTEGER(42);
|
||||||
|
Toy_Value question = TOY_VALUE_FROM_INTEGER(42);
|
||||||
|
Toy_Value nope = TOY_VALUE_FROM_NULL();
|
||||||
|
|
||||||
|
if (Toy_checkValuesAreComparable(answer, question) != true) {
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: value comparison check failed, expected true\n" TOY_CC_RESET);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Toy_checkValuesAreComparable(answer, nope) != false) {
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: value comparison check failed, expected false\n" TOY_CC_RESET);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//test comparison
|
||||||
|
{
|
||||||
|
Toy_Value answer = TOY_VALUE_FROM_INTEGER(42);
|
||||||
|
Toy_Value question = TOY_VALUE_FROM_INTEGER(42);
|
||||||
|
Toy_Value nice = TOY_VALUE_FROM_INTEGER(69);
|
||||||
|
|
||||||
|
if (Toy_compareValues(answer, question) != 0) {
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: value comparison failed, expected 0\n" TOY_CC_RESET);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Toy_compareValues(answer, nice) == 0) {
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: value comparison failed, expected not 0\n" TOY_CC_RESET);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//again with strings
|
||||||
|
{
|
||||||
|
//setup
|
||||||
|
Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_SMALL);
|
||||||
|
|
||||||
|
Toy_Value answer = TOY_VALUE_FROM_STRING(Toy_createString(&bucket, "poe wrote on both"));
|
||||||
|
Toy_Value question = TOY_VALUE_FROM_STRING(Toy_createString(&bucket, "why is a raven like a writing desk?"));
|
||||||
|
Toy_Value duplicate = TOY_VALUE_FROM_STRING(Toy_createString(&bucket, "poe wrote on both"));
|
||||||
|
|
||||||
|
if (Toy_compareValues(answer, duplicate) != 0) {
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: string value comparison failed, expected 0\n" TOY_CC_RESET);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Toy_compareValues(answer, question) == 0) {
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: string value comparison failed, expected not 0\n" TOY_CC_RESET);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
Toy_freeBucket(&bucket);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_value_hashing() {
|
||||||
//test value hashing
|
//test value hashing
|
||||||
{
|
{
|
||||||
//setup
|
//setup
|
||||||
@@ -87,6 +202,47 @@ int main() {
|
|||||||
Toy_freeBucket(&bucket);
|
Toy_freeBucket(&bucket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//NOTE: string hash is a PITA, skipping
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
//run each test set, returning the total errors given
|
||||||
|
int total = 0, res = 0;
|
||||||
|
|
||||||
|
{
|
||||||
|
res = test_value_creation();
|
||||||
|
if (res == 0) {
|
||||||
|
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||||
|
}
|
||||||
|
total += res;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
res = test_value_equality();
|
||||||
|
if (res == 0) {
|
||||||
|
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||||
|
}
|
||||||
|
total += res;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
res = test_value_comparison();
|
||||||
|
if (res == 0) {
|
||||||
|
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||||
|
}
|
||||||
|
total += res;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
res = test_value_hashing();
|
||||||
|
if (res == 0) {
|
||||||
|
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||||
|
}
|
||||||
|
total += res;
|
||||||
|
}
|
||||||
|
|
||||||
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,3 +17,39 @@ answer *= 9;
|
|||||||
answer /= 2;
|
answer /= 2;
|
||||||
answer %= 10;
|
answer %= 10;
|
||||||
|
|
||||||
|
//equality checks
|
||||||
|
print 1 == 1; //true
|
||||||
|
print 1 != 1; //false
|
||||||
|
|
||||||
|
//comparison checks
|
||||||
|
print 1 < 2; //true
|
||||||
|
|
||||||
|
print "foo" > "bar"; //true
|
||||||
|
|
||||||
|
print 1 < 2; //true
|
||||||
|
print 1 > 2; //false
|
||||||
|
|
||||||
|
print 2 <= 2; //true
|
||||||
|
print 2 >= 2; //true
|
||||||
|
|
||||||
|
print 1 <= 2; //true
|
||||||
|
print 1 >= 2; //false
|
||||||
|
|
||||||
|
//logical checks
|
||||||
|
print true && true; //true
|
||||||
|
print true && false; //false
|
||||||
|
print false && true; //false
|
||||||
|
print false && false; //false
|
||||||
|
|
||||||
|
print true || true; //true
|
||||||
|
print true || false; //true
|
||||||
|
print false || true; //true
|
||||||
|
print false || false; //false
|
||||||
|
|
||||||
|
print !true; //false
|
||||||
|
print !false; //true
|
||||||
|
|
||||||
|
//precedence
|
||||||
|
print true && false || true; //TODO: a warning is needed for this
|
||||||
|
|
||||||
|
//TODO: type casting
|
||||||
Reference in New Issue
Block a user