mirror of https://github.com/japl-lang/japl.git
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:
parent
ff0ec33991
commit
68b10602b5
|
@ -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}"
|
||||
|
|
|
@ -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:
|
||||
|
|
23
nim/vm.nim
23
nim/vm.nim
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue