mirror of https://github.com/japl-lang/japl.git
Added bitwise operators
This commit is contained in:
parent
556a130172
commit
cedb3bc44b
|
@ -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
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -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('*'):
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
import segfaults
|
||||
import types/objecttype
|
||||
import common
|
||||
|
||||
|
||||
proc reallocate*(pointer: pointer, oldSize: int, newSize: int): pointer =
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 =
|
||||
|
|
18
nim/vm.nim
18
nim/vm.nim
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue