Added support for negative slice indexes, fixed a couple bugs and refactored the lexer a bit to use the new methods to convert from and to JAPL values

This commit is contained in:
nocturn9x 2020-08-24 08:05:12 +02:00
parent ff0ec33991
commit 68b10602b5
3 changed files with 33 additions and 16 deletions

View File

@ -105,7 +105,7 @@ proc parseString(self: var Lexer, delimiter: char) =
echo &"SyntaxError: Unterminated string literal at line {self.line}"
self.errored = true
discard self.step()
let value = Value(kind: ValueTypes.OBJECT, obj: newString(self.source[self.start..<self.current])) # Get the value between quotes
let value = self.source[self.start..<self.current].asStr() # Get the value between quotes
let token = self.createToken(STR, value)
self.tokens.add(token)
@ -118,10 +118,10 @@ proc parseNumber(self: var Lexer) =
discard self.step()
while self.peek().isDigit():
discard self.step()
var value = Value(kind: ValueTypes.DOUBLE, floatValue: parseFloat(self.source[self.start..<self.current]))
var value = parseFloat(self.source[self.start..<self.current]).asFloat()
self.tokens.add(self.createToken(TokenType.NUMBER, value))
else:
var value = Value(kind: ValueTypes.INTEGER, intValue: parseInt(self.source[self.start..<self.current]))
var value = parseInt(self.source[self.start..<self.current]).asInt()
self.tokens.add(self.createToken(TokenType.NUMBER, value))
except ValueError:
echo "OverflowError: integer is too big"
@ -134,9 +134,9 @@ proc parseIdentifier(self: var Lexer) =
var text: string = self.source[self.start..<self.current]
var keyword = text in RESERVED
if keyword:
self.tokens.add(self.createToken(RESERVED[text], Value(kind: ValueTypes.OBJECT, obj: newString(text))))
self.tokens.add(self.createToken(RESERVED[text], text.asStr()))
else:
self.tokens.add(self.createToken(ID, Value(kind: ValueTypes.OBJECT, obj: newString(text))))
self.tokens.add(self.createToken(ID, text.asStr()))
proc parseComment(self: var Lexer) =
@ -177,17 +177,17 @@ proc scanToken(self: var Lexer) =
elif single == '/' and self.match('*'):
self.parseComment()
elif single == '=' and self.match('='):
self.tokens.add(self.createToken(DEQ, Value(kind: ValueTypes.OBJECT, obj: newString("=="))))
self.tokens.add(self.createToken(DEQ, "==".asStr()))
elif single == '>' and self.match('='):
self.tokens.add(self.createToken(GE, Value(kind: ValueTypes.OBJECT, obj: newString(">="))))
self.tokens.add(self.createToken(GE, ">=".asStr()))
elif single == '<' and self.match('='):
self.tokens.add(self.createToken(LE, Value(kind: ValueTypes.OBJECT, obj: newString("<="))))
self.tokens.add(self.createToken(LE, "<=".asStr()))
elif single == '!' and self.match('='):
self.tokens.add(self.createToken(NE, Value(kind: ValueTypes.OBJECT, obj: newString("!="))))
self.tokens.add(self.createToken(NE, "!=".asStr()))
elif single == '*' and self.match('*'):
self.tokens.add(self.createToken(POW, Value(kind: ValueTypes.OBJECT, obj: newString("**"))))
self.tokens.add(self.createToken(POW, "**".asStr()))
else:
self.tokens.add(self.createToken(TOKENS[single], Value(kind: ValueTypes.OBJECT, obj: newString(&"{single}"))))
self.tokens.add(self.createToken(TOKENS[single], asStr(&"{single}")))
else:
self.errored = true
echo &"SyntaxError: Unexpected character '{single}' at line {self.line}"

View File

@ -110,6 +110,10 @@ func asBool*(b: bool): Value =
result = Value(kind: BOOL, boolValue: b)
proc asStr*(s: string): Value =
result = Value(kind: OBJECT, obj: newString(s))
func stringify*(value: Value): string =
case value.kind:
of INTEGER:

View File

@ -73,7 +73,10 @@ proc slice(self: VM): bool =
self.error(newTypeError("string indeces must be integers"))
return false
elif idx.toInt() < 0:
idx.intValue = (len(str) - 1) - (-idx.toInt())
idx.intValue = len(str) + idx.toInt()
if idx.toInt() < 0:
self.error(newIndexError("string index out of bounds"))
return false
if idx.toInt() - 1 > len(str) - 1:
self.error(newIndexError("string index out of bounds"))
return false
@ -101,14 +104,24 @@ proc sliceRange(self: VM): bool =
sliceEnd = Value(kind: INTEGER, intValue: len(str))
if sliceStart.isNil():
sliceStart = Value(kind: INTEGER, intValue: 0)
if not sliceStart.isInt() or not sliceEnd.isInt():
elif not sliceStart.isInt() or not sliceEnd.isInt():
self.error(newTypeError("string indeces must be integers"))
return false
elif sliceStart.toInt() - 1 > len(str) - 1 or sliceEnd.toInt() - 1 > len(str) - 1:
elif sliceStart.toInt() < 0:
sliceStart.intValue = len(str) + sliceStart.toInt()
if sliceStart.toInt() < 0:
self.error(newIndexError("string index out of bounds"))
return false
if sliceEnd.toInt() < 0:
sliceEnd.intValue = len(str) + sliceEnd.toInt()
if sliceEnd.toInt() < 0:
self.error(newIndexError("string index out of bounds"))
return false
if sliceStart.toInt() - 1 > len(str) - 1 or sliceEnd.toInt() - 1 > len(str) - 1:
self.error(newIndexError("string index out of bounds"))
return false
elif sliceStart.toInt() < 0 or sliceEnd.toInt() < 0:
self.error(newIndexError("string index out of bounds"))
elif sliceStart.toInt() > sliceEnd.toInt():
self.error(newIndexError("the start index can't be bigger than the end index"))
return false
self.push(Value(kind: OBJECT, obj: newString(str[sliceStart.toInt()..<sliceEnd.toInt()])))
return true