Added bitwise operators

This commit is contained in:
nocturn9x 2020-08-30 12:35:37 +02:00
parent 556a130172
commit cedb3bc44b
7 changed files with 64 additions and 8 deletions

View File

@ -84,6 +84,7 @@ proc compileError(self: var Compiler, message: string) =
self.parser.hadError = true
self.parser.panicMode = true
proc emitByte(self: var Compiler, byt: OpCode|uint8) =
self.function.chunk.writeChunk(uint8 byt, self.parser.previous().line)
@ -179,6 +180,12 @@ proc binary(self: var Compiler, canAssign: bool) =
self.emitByte(OP_LESS)
of LE:
self.emitBytes(OP_GREATER, OP_NOT)
of CARET:
self.emitByte(OP_XOR)
of SHL:
self.emitByte(OP_SHL)
of SHR:
self.emitByte(OP_SHR)
else:
return
@ -250,6 +257,10 @@ proc literal(self: var Compiler, canAssign: bool) =
self.emitByte(OP_FALSE)
of TokenType.NIL:
self.emitByte(OP_NIL)
of TokenType.INF:
self.emitByte(OP_INF)
of TokenType.NAN:
self.emitByte(OP_NAN)
else:
discard # Unreachable
@ -765,7 +776,11 @@ var rules: array[TokenType, ParseRule] = [
makeRule(nil, nil, PREC_NONE), # EOF
makeRule(nil, nil, PREC_NONE), # COLON
makeRule(nil, nil, PREC_NONE), # CONTINUE
makeRule(nil, nil, PREC_NONE), # CARET
makeRule(nil, binary, PREC_TERM), # CARET
makeRule(nil, binary, PREC_TERM), # SHL
makeRule(nil, binary, PREC_TERM), # SHR
makeRule(literal, nil, PREC_NONE), # INF
makeRule(literal, nil, PREC_NONE), # NAN
]

View File

@ -37,7 +37,8 @@ const RESERVED = to_table({
"return": TokenType.RETURN,
"this": TokenType.THIS, "super": TokenType.SUPER,
"del": TokenType.DEL, "break": TokenType.BREAK,
"continue": TokenType.CONTINUE})
"continue": TokenType.CONTINUE, "inf": TokenType.INF,
"nan": TokenType.NAN})
type
Lexer* = ref object
source*: string
@ -184,8 +185,12 @@ proc scanToken(self: var Lexer) =
self.tokens.add(self.createToken(DEQ, "==".asStr()))
elif single == '>' and self.match('='):
self.tokens.add(self.createToken(GE, ">=".asStr()))
elif single == '>' and self.match('>'):
self.tokens.add(self.createToken(SHR, ">>".asStr()))
elif single == '<' and self.match('='):
self.tokens.add(self.createToken(LE, "<=".asStr()))
elif single == '<' and self.match('<'):
self.tokens.add(self.createToken(SHL, ">>".asStr()))
elif single == '!' and self.match('='):
self.tokens.add(self.createToken(NE, "!=".asStr()))
elif single == '*' and self.match('*'):

View File

@ -9,7 +9,6 @@
import segfaults
import types/objecttype
import common
proc reallocate*(pointer: pointer, oldSize: int, newSize: int): pointer =

View File

@ -34,6 +34,13 @@ type
OP_JUMP,
OP_LOOP,
OP_BREAK,
OP_SHR,
OP_SHL,
OP_NAN,
OP_INF,
OP_XOR
Chunk* = ref object
consts*: ValueArray
code*: seq[uint8]

View File

@ -12,4 +12,5 @@ type
IF, NIL, RETURN, SUPER,
THIS, OR, TRUE, VAR,
WHILE, DEL, BREAK, EOF,
COLON, CONTINUE, CARET
COLON, CONTINUE, CARET,
SHL, SHR, NAN, INF

View File

@ -13,7 +13,7 @@ import strutils
type
ValueTypes* = enum # All possible value types (this is the VM's notion of 'type', not the end user's)
INTEGER, DOUBLE, BOOL, NIL, OBJECT
INTEGER, DOUBLE, BOOL, NIL, OBJECT, NAN, INF
Value* = object
case kind*: ValueTypes
of INTEGER:
@ -22,7 +22,7 @@ type
floatValue*: float
of BOOL:
boolValue*: bool
of NIL:
of NIL, INF, NAN:
discard
of OBJECT:
obj*: ptr Obj
@ -81,7 +81,7 @@ func toFloat*(value: Value): float =
func typeName*(value: Value): string =
case value.kind:
of BOOL, NIL, DOUBLE, INTEGER:
of BOOL, NIL, DOUBLE, INTEGER, NAN, INF:
result = ($value.kind).toLowerAscii()
of OBJECT:
case value.obj.kind:
@ -132,6 +132,10 @@ func stringify*(value: Value): string =
result = cast[ptr String](value.obj)[].stringify
else:
result = value.obj[].stringify()
of NAN:
result = "nan"
of INF:
result = "nil"
func isFalsey*(value: Value): bool =
@ -146,7 +150,10 @@ func isFalsey*(value: Value): bool =
result = value.toFloat() > 0.0
of NIL:
result = true
of INF:
result = false
of NAN:
result = true
proc valuesEqual*(a: Value, b: Value): bool =
if a.kind != b.kind:
@ -169,6 +176,10 @@ proc valuesEqual*(a: Value, b: Value): bool =
result = valuesEqual(a[], b[])
else:
result = valuesEqual(a.obj[], b.obj[])
of INF:
result = b.kind == INF
of NAN:
result = false
proc hashFloat(f: float): uint32 =

View File

@ -192,6 +192,14 @@ proc run(self: var VM, debug, repl: bool): InterpretResult =
else:
self.error(newTypeError(&"Unsupported binary operator for objects of type '{leftVal.typeName()}' and '{rightVal.typeName()}'"))
return RUNTIME_ERROR
template BitWise(op): untyped =
var rightVal {.inject.} = self.pop()
var leftVal {.inject.} = self.pop()
if isInt(leftVal) and isInt(rightVal):
self.push(Value(kind: INTEGER, intValue: `op`(leftVal.toInt(), rightVal.toInt())))
else:
self.error(newTypeError(&"Unsupported binary operator for objects of type '{leftVal.typeName()}' and '{rightVal.typeName()}'"))
return RUNTIME_ERROR
var instruction: uint8
var opcode: OpCode
while true:
@ -246,6 +254,12 @@ proc run(self: var VM, debug, repl: bool): InterpretResult =
return RUNTIME_ERROR
else:
BinOp(`+`, isNum)
of OP_SHL:
BitWise(`shl`)
of OP_SHR:
BitWise(`shr`)
of OP_XOR:
BitWise(`xor`)
of OP_SUBTRACT:
BinOp(`-`, isNum)
of OP_DIVIDE:
@ -279,6 +293,10 @@ proc run(self: var VM, debug, repl: bool): InterpretResult =
self.push(Value(kind: BOOL, boolValue: false))
of OP_NIL:
self.push(Value(kind: NIL))
of OP_NAN:
self.push(Value(kind: ValueTypes.NAN))
of OP_INF:
self.push(Value(kind: ValueTypes.INF))
of OP_NOT:
self.push(Value(kind: BOOL, boolValue: isFalsey(self.pop())))
of OP_EQUAL: