diff --git a/lang/bytecode.c b/lang/bytecode.c index 11fabdd..bdb410d 100644 --- a/lang/bytecode.c +++ b/lang/bytecode.c @@ -2,6 +2,7 @@ // Copyright (c) 2023 John Watts and the LuminaSensum contributors #include "bytecode.h" +#include "boolean.h" #include "error.h" #include "number.h" #include "object.h" @@ -20,7 +21,8 @@ OP_SET = 0x07, OP_DROP = 0x08, OP_DEPTH_CHECK = 0x09, - OP_SELF = 0x0A + OP_SELF = 0x0A, + OP_BOOLEAN = 0x0B, }; void bytecode_run(VmState state, Object obj, const unsigned char *bytecode) { @@ -39,6 +41,14 @@ vm_stack_push(state, number_create(num)); break; } + // OP_BOOLEAN pushes a boolean on to the stack + // First argument is a 1-byte boolean + case OP_BOOLEAN: { + int value = *pos_code++; + abort_if(value != 0 && value != 1, "invalid boolean"); + vm_stack_push(state, boolean_create(value)); + break; + } // OP_CALL dispatches a call to the top of stack object // First argument is a 1-byte argument count // Second argument is the call string diff --git a/lang/compile.py b/lang/compile.py index ade767a..eb5cef7 100755 --- a/lang/compile.py +++ b/lang/compile.py @@ -20,6 +20,13 @@ def __repr__(self): return 'ASTNumber(number=%i)' % (self.number) +class ASTBoolean(): + def __init__(self, value): + self.value = value + + def __repr__(self): + return 'ASTBoolean(value=%s)' % (self.value) + class ASTReference(): def __init__(self, name): self.name = name @@ -84,6 +91,10 @@ def parse_value(val): if val[0].isdigit(): return ASTNumber(int(val)) + elif val == "True": + return ASTBoolean(True) + elif val == "False": + return ASTBoolean(False) else: return ASTReference(val) @@ -190,6 +201,13 @@ def __repr__(self): return 'IRNumber(number=%i)' % (self.number) +class IRBoolean(): + def __init__(self, value): + self.value = value + + def __repr__(self): + return 'IRBoolean(value=%s)' % (self.value) + class IRAllocate(): def __init__(self, size): self.size = size @@ -255,6 +273,8 @@ def generate_ir_value(value): if isinstance(value, ASTNumber): return [IRNumber(value.number)] + elif isinstance(value, ASTBoolean): + return [IRBoolean(value.value)] elif isinstance(value, ASTReference): if value.name == "Self": return [IRSelf()] @@ -417,6 +437,10 @@ if isinstance(node, IRNumber): bytes += b"\x01" # OP_NUM bytes += node.number.to_bytes(4, 'little') + elif isinstance(node, IRBoolean): + bool_value = int(node.value == 1) + bytes += b"\x0B" # OP_BOOLEAN + bytes += bool_value.to_bytes(1, 'little') elif isinstance(node, IRAllocate): for i in range(0, node.size): bytes += b"\x05" # OP_NULL diff --git a/lang/main.c b/lang/main.c index 0cc2f46..d6c06d0 100644 --- a/lang/main.c +++ b/lang/main.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT // Copyright (c) 2023 John Watts and the LuminaSensum contributors +#include "boolean.h" #include "error.h" #include "number.h" #include "object.h" @@ -29,6 +30,12 @@ Object numA = vm_stack_pop(state); printf("code return value is %i\n", number_value(numA)); abort_if(number_value(numA) != 1234, "code return value is not 1234"); + vm_stack_push(state, object_none()); + vm_call(state, module, "BoolTest", 1); + Object boolA = vm_stack_pop(state); + abort_if( + boolean_value(boolA) != false, "code return bool is not false"); + object_drop(&boolA); object_drop(&numA); object_drop(&module); } diff --git a/lang/modules/main.txt b/lang/modules/main.txt index b4af27a..710a389 100644 --- a/lang/modules/main.txt +++ b/lang/modules/main.txt @@ -1,3 +1,8 @@ +Function BoolTest +Set A To True +Set B To A Not +Return B +EndFunction Function GetHalfish Args Num Set FinalNum To Num Minus 2 Return FinalNum