Added all missing comparison operators and fixed error reporting system

This commit is contained in:
Mattia Giambirtone 2022-08-15 22:15:06 +02:00
parent 5dc8ce437c
commit 626375bc1f
8 changed files with 276 additions and 18 deletions

View File

@ -692,6 +692,46 @@ proc dispatch*(self: PeonVM) =
self.push(PeonObject(kind: Bool, boolean: self.pop().halfFloat == self.pop().halfFloat))
of NotEqualFloat32:
self.push(PeonObject(kind: Bool, boolean: self.pop().halfFloat != self.pop().halfFloat))
of GreaterOrEqualInt64:
self.push(PeonObject(kind: Bool, boolean: self.pop().long !>= self.pop().long))
of LessOrEqualInt64:
self.push(PeonObject(kind: Bool, boolean: self.pop().long <= self.pop().long))
of GreaterOrEqualUInt64:
self.push(PeonObject(kind: Bool, boolean: self.pop().uLong !>= self.pop().uLong))
of LessOrEqualUInt64:
self.push(PeonObject(kind: Bool, boolean: self.pop().uLong <= self.pop().uLong))
of GreaterOrEqualInt32:
self.push(PeonObject(kind: Bool, boolean: self.pop().`int` !>= self.pop().`int`))
of LessOrEqualInt32:
self.push(PeonObject(kind: Bool, boolean: self.pop().`int` <= self.pop().`int`))
of GreaterOrEqualUInt32:
self.push(PeonObject(kind: Bool, boolean: self.pop().uInt !>= self.pop().uInt))
of LessOrEqualUInt32:
self.push(PeonObject(kind: Bool, boolean: self.pop().uInt <= self.pop().uInt))
of GreaterOrEqualInt16:
self.push(PeonObject(kind: Bool, boolean: self.pop().short !>= self.pop().short))
of LessOrEqualInt16:
self.push(PeonObject(kind: Bool, boolean: self.pop().short <= self.pop().short))
of GreaterOrEqualUInt16:
self.push(PeonObject(kind: Bool, boolean: self.pop().uShort !>= self.pop().uShort))
of LessOrEqualUInt16:
self.push(PeonObject(kind: Bool, boolean: self.pop().uShort <= self.pop().uShort))
of GreaterOrEqualInt8:
self.push(PeonObject(kind: Bool, boolean: self.pop().tiny !>= self.pop().tiny))
of LessOrEqualInt8:
self.push(PeonObject(kind: Bool, boolean: self.pop().tiny <= self.pop().tiny))
of GreaterOrEqualUInt8:
self.push(PeonObject(kind: Bool, boolean: self.pop().uTiny !>= self.pop().uTiny))
of LessOrEqualUInt8:
self.push(PeonObject(kind: Bool, boolean: self.pop().uTiny <= self.pop().uTiny))
of GreaterOrEqualFloat64:
self.push(PeonObject(kind: Bool, boolean: self.pop().`float` !>= self.pop().`float`))
of LessOrEqualFloat64:
self.push(PeonObject(kind: Bool, boolean: self.pop().`float` <= self.pop().`float`))
of GreaterOrEqualFloat32:
self.push(PeonObject(kind: Bool, boolean: self.pop().halfFloat !>= self.pop().halfFloat))
of LessOrEqualFloat32:
self.push(PeonObject(kind: Bool, boolean: self.pop().halfFloat <= self.pop().halfFloat))
of SysClock64:
# Pushes the value of a monotonic clock
# as a 64 bit float onto the operand stack.

View File

@ -1103,6 +1103,46 @@ proc handleBuiltinFunction(self: Compiler, fn: Name, args: seq[Expression]) =
self.emitByte(EqualFloat32)
of "NotEqualFloat32":
self.emitByte(NotEqualFloat32)
of "GreaterOrEqualInt64":
self.emitByte(GreaterOrEqualInt64)
of "LessOrEqualInt64":
self.emitByte(LessOrEqualInt64)
of "GreaterOrEqualUInt64":
self.emitByte(GreaterOrEqualUInt64)
of "LessOrEqualUInt64":
self.emitByte(LessOrEqualUInt64)
of "GreaterOrEqualInt32":
self.emitByte(GreaterOrEqualInt32)
of "LessOrEqualInt32":
self.emitByte(LessOrEqualInt32)
of "GreaterOrEqualUInt32":
self.emitByte(GreaterOrEqualUInt32)
of "LessOrEqualUInt32":
self.emitByte(LessOrEqualUInt32)
of "GreaterOrEqualInt16":
self.emitByte(GreaterOrEqualInt16)
of "LessOrEqualInt16":
self.emitByte(LessOrEqualInt16)
of "GreaterOrEqualUInt16":
self.emitByte(GreaterOrEqualUInt16)
of "LessOrEqualUInt16":
self.emitByte(LessOrEqualUInt16)
of "GreaterOrEqualInt8":
self.emitByte(GreaterOrEqualInt8)
of "LessOrEqualInt8":
self.emitByte(LessOrEqualInt8)
of "GreaterOrEqualUInt8":
self.emitByte(GreaterOrEqualUInt8)
of "LessOrEqualUInt8":
self.emitByte(LessOrEqualUInt8)
of "GreaterOrEqualFloat64":
self.emitByte(GreaterOrEqualFloat64)
of "LessOrEqualFloat64":
self.emitByte(LessOrEqualFloat64)
of "GreaterOrEqualFloat32":
self.emitByte(GreaterOrEqualFloat32)
of "LessOrEqualFloat32":
self.emitByte(LessOrEqualFloat32)
of "SysClock64":
self.emitByte(SysClock64)
else:

View File

@ -237,7 +237,6 @@ proc peek(self: Lexer, distance: int = 0, length: int = 1): string =
proc error(self: Lexer, message: string) =
## Raises a lexing error with info
## for error messages
echo self.source[self.current - 50..self.current]
raise LexingError(msg: message, line: self.line, file: self.file, lexeme: self.peek(), lexer: self)
@ -297,9 +296,7 @@ proc createToken(self: Lexer, tokenType: TokenType) =
tok.line = self.line
tok.spaces = self.spaces
self.spaces = 0
tok.pos = (start: self.start, stop: self.current)
if len(tok.lexeme) != tok.pos.stop - tok.pos.start:
self.error("invalid state: len(tok.lexeme) != tok.pos.stop - tok.pos.start (this is most likely a compiler bug!)")
tok.pos = (start: self.start, stop: self.current - 1)
self.tokens.add(tok)
@ -616,6 +613,7 @@ proc next(self: Lexer) =
while not (self.match("\n") or self.done()):
discard self.step()
self.createToken(Comment)
self.incLine()
else:
self.createToken(Pragma)
else:

View File

@ -177,6 +177,26 @@ type
GreaterThanFloat32,
EqualFloat32,
NotEqualFloat32,
GreaterOrEqualInt64,
LessOrEqualInt64,
GreaterOrEqualUInt64,
LessOrEqualUInt64,
GreaterOrEqualInt32,
LessOrEqualInt32,
GreaterOrEqualUInt32,
LessOrEqualUInt32,
GreaterOrEqualInt16,
LessOrEqualInt16,
GreaterOrEqualUInt16,
LessOrEqualUInt16,
GreaterOrEqualInt8,
LessOrEqualInt8,
GreaterOrEqualUInt8,
LessOrEqualUInt8,
GreaterOrEqualFloat64,
LessOrEqualFloat64,
GreaterOrEqualFloat32,
LessOrEqualFloat32,
SysClock64,
## Basic stack operations
Pop, # Pops an element off the stack and discards it
@ -253,6 +273,27 @@ const simpleInstructions* = {Return, LoadNil,
NotEqualUInt8, LessThanFloat64, GreaterThanFloat64,
EqualFloat64,NotEqualFloat64, LessThanFloat32,
GreaterThanFloat32, EqualFloat32, NotEqualFloat32,
GreaterOrEqualInt64,
LessOrEqualInt64,
GreaterOrEqualUInt64,
LessOrEqualUInt64,
GreaterOrEqualInt32,
LessOrEqualInt32,
GreaterOrEqualUInt32,
LessOrEqualUInt32,
GreaterOrEqualInt16,
LessOrEqualInt16,
GreaterOrEqualUInt16,
LessOrEqualUInt16,
GreaterOrEqualInt8,
LessOrEqualInt8,
GreaterOrEqualUInt8,
LessOrEqualUInt8,
GreaterOrEqualFloat64,
LessOrEqualFloat64,
GreaterOrEqualFloat32,
LessOrEqualFloat32,
SysClock64,
}
# Constant instructions are instructions that operate on the bytecode constant table

View File

@ -208,6 +208,7 @@ proc step(self: Parser, n: int = 1): Token =
proc error(self: Parser, message: string, token: Token = nil) {.raises: [ParseError].} =
## Raises a ParseError exception
echo (if token.isNil(): self.getCurrentToken() else: token)[]
raise ParseError(msg: message, token: if token.isNil(): self.getCurrentToken() else: token, file: self.file, module: self.getModule(), parser: self)

View File

@ -141,11 +141,11 @@ proc repl(vm: PeonVM = newPeonVM()) =
except LexingError:
input = ""
let exc = LexingError(getCurrentException())
let relPos = tokenizer.getRelPos(exc.line)
let line = tokenizer.getSource().splitLines()[exc.line - 1].strip(chars={'\n'})
let relPos = exc.lexer.getRelPos(exc.line)
let line = exc.lexer.getSource().splitLines()[exc.line - 1].strip(chars={'\n'})
stderr.styledWriteLine(fgRed, "A fatal error occurred while parsing ", fgYellow, &"'{exc.file}'", fgRed, ", module ",
fgYellow, &"'{exc.file.extractFilename()}'", fgRed, ", line ", fgYellow, $exc.line, fgRed, " at ", fgYellow, &"'{exc.lexeme.escape()}'",
fgRed, ": ", fgGreen , getCurrentExceptionMsg())
fgYellow, &"'{exc.file.extractFilename()}'", fgRed, ", line ", fgYellow, $exc.line, fgRed, " at ", fgYellow, &"'{exc.lexeme.escape()}'",
fgRed, ": ", fgGreen , getCurrentExceptionMsg())
styledEcho fgBlue, "Source line: " , fgDefault, line
styledEcho fgCyan, " ".repeat(len("Source line: ")) & "^".repeat(relPos.stop - relPos.start)
except ParseError:
@ -153,30 +153,30 @@ proc repl(vm: PeonVM = newPeonVM()) =
let exc = ParseError(getCurrentException())
let lexeme = exc.token.lexeme
let lineNo = exc.token.line
let relPos = tokenizer.getRelPos(lineNo)
let relPos = exc.parser.getRelPos(lineNo)
let fn = parser.getCurrentFunction()
let line = tokenizer.getSource().splitLines()[lineNo - 1].strip(chars={'\n'})
let line = exc.parser.getSource().splitLines()[lineNo - 1].strip(chars={'\n'})
var fnMsg = ""
if fn != nil and fn.kind == funDecl:
fnMsg &= &"in function '{FunDecl(fn).name.token.lexeme}'"
stderr.styledWriteLine(fgRed, "A fatal error occurred while parsing ", fgYellow, &"'{exc.file}'", fgRed, ", module ",
fgYellow, &"'{exc.file}'", fgRed, ", line ", fgYellow, $lineNo, fgRed, " at ", fgYellow, &"'{lexeme}'",
fgRed, ": ", fgGreen , getCurrentExceptionMsg())
fgYellow, &"'{exc.module}'", fgRed, ", line ", fgYellow, $lineNo, fgRed, " at ", fgYellow, &"'{lexeme}'",
fgRed, ": ", fgGreen , getCurrentExceptionMsg())
styledEcho fgBlue, "Source line: " , fgDefault, line
styledEcho fgCyan, " ".repeat(len("Source line: ")) & "^".repeat(relPos.stop - relPos.start)
except CompileError:
let exc = CompileError(getCurrentException())
let lexeme = exc.node.token.lexeme
let lineNo = exc.node.token.line
let relPos = tokenizer.getRelPos(lineNo)
let line = tokenizer.getSource().splitLines()[lineNo - 1].strip(chars={'\n'})
var fn = compiler.getCurrentFunction()
let relPos = exc.compiler.getRelPos(lineNo)
let line = exc.compiler.getSource().splitLines()[lineNo - 1].strip(chars={'\n'})
var fn = exc.compiler.getCurrentFunction()
var fnMsg = ""
if fn != nil and fn.kind == funDecl:
fnMsg &= &"in function '{FunDecl(fn).name.token.lexeme}'"
stderr.styledWriteLine(fgRed, "A fatal error occurred while compiling ", fgYellow, &"'{exc.file}'", fgRed, ", module ",
fgYellow, &"'{exc.module}'", fgRed, ", line ", fgYellow, $lineNo, fgRed, " at ", fgYellow, &"'{lexeme}'",
fgRed, ": ", fgGreen , getCurrentExceptionMsg())
fgYellow, &"'{exc.module}'", fgRed, ", line ", fgYellow, $lineNo, fgRed, " at ", fgYellow, &"'{lexeme}'",
fgRed, ": ", fgGreen , getCurrentExceptionMsg())
styledEcho fgBlue, "Source line: " , fgDefault, line
styledEcho fgCyan, " ".repeat(len("Source line: ")) & "^".repeat(relPos.stop - relPos.start)
except SerializationError:

View File

@ -1,5 +1,4 @@
import std;
# int64
print(3 > 2); # true
print(2 < 3); # true
@ -9,6 +8,10 @@ print(2 != 3); # true
print(3 != 2); # true
print(3 == 2); # false
print(2 == 3); # false
print(2 <= 3); # true
print(3 >= 2); # true
print(2 >= 3); # false
print(3 <= 2); # false
# uint64
var x = 3'u64;
var y = 2'u64;
@ -20,6 +23,10 @@ print(y != x); # true
print(x != y); # true
print(x == y); # false
print(y == x); # false
print(y <= x); # true
print(x >= y); # true
print(y >= x); # false
print(x <= y); # false
# int32
var x1 = 3'i32;
var y1 = 2'i32;
@ -31,6 +38,10 @@ print(y1 != x1); # true
print(x1 != y1); # true
print(x1 == y1); # false
print(y1 == x1); # false
print(y1 <= x1); # true
print(x1 >= y1); # true
print(y1 >= x1); # false
print(x1 <= y1); # false
# uint32
var x2 = 3'u32;
var y2 = 2'u32;
@ -42,6 +53,10 @@ print(y2 != x2); # true
print(x2 != y2); # true
print(x2 == y2); # false
print(y2 == x2); # false
print(y2 <= x2); # true
print(x2 >= y2); # true
print(y2 >= x2); # false
print(x2 <= y2); # false
# int16
var x3 = 3'i16;
var y3 = 2'i16;
@ -53,6 +68,10 @@ print(y3 != x3); # true
print(x3 != y3); # true
print(x3 == y3); # false
print(y3 == x3); # false
print(y3 <= x3); # true
print(x3 >= y3); # true
print(y3 >= x3); # false
print(x3 <= y3); # false
# uint16
var x4 = 3'u16;
var y4 = 2'u16;
@ -64,6 +83,10 @@ print(y4 != x4); # true
print(x4 != y4); # true
print(x4 == y4); # false
print(y4 == x4); # false
print(y4 <= x4); # true
print(x4 >= y4); # true
print(y4 >= x4); # false
print(x4 <= y4); # false
# int8
var x5 = 3'i8;
var y5 = 2'i8;
@ -75,6 +98,10 @@ print(y5 != x5); # true
print(x5 != y5); # true
print(x5 == y5); # false
print(y5 == x5); # false
print(y5 <= x5); # true
print(x5 >= y5); # true
print(y5 >= x5); # false
print(x5 <= y5); # false
# uint8
var x6 = 3'u8;
var y6 = 2'u8;
@ -86,6 +113,10 @@ print(y6 != x6); # true
print(x6 != y6); # true
print(x6 == y6); # false
print(y6 == x6); # false
print(y6 <= x6); # true
print(x6 >= y6); # true
print(y6 >= x6); # false
print(x6 <= y6); # false
# float64
var x7 = 3.0;
var y7 = 2.0;
@ -97,6 +128,10 @@ print(y7 != x7); # true
print(x7 != y7); # true
print(x7 == y7); # false
print(y7 == x7); # false
print(y7 <= x7); # true
print(x7 >= y7); # true
print(y7 >= x7); # false
print(x7 <= y7); # false
# float32
var x8 = 3'f32;
var y8 = 2'f32;
@ -108,3 +143,7 @@ print(y8 != x8); # true
print(x8 != y8); # true
print(x8 == y8); # false
print(y8 == x8); # false
print(y8 <= x8); # true
print(x8 >= y8); # true
print(y8 >= x8); # false
print(x8 <= y8); # false

View File

@ -408,6 +408,105 @@ operator `!=`*(a, b: float32): bool {
}
operator `>=`*(a, b: int): bool {
#pragma[magic: "GreaterOrEqualInt64", pure]
}
operator `<=`*(a, b: int): bool {
#pragma[magic: "LessOrEqualInt64", pure]
}
operator `>=`*(a, b: uint64): bool {
#pragma[magic: "GreaterOrEqualUInt64", pure]
}
operator `<=`*(a, b: uint64): bool {
#pragma[magic: "LessOrEqualUInt64", pure]
}
operator `>=`*(a, b: int32): bool {
#pragma[magic: "GreaterOrEqualInt32", pure]
}
operator `<=`*(a, b: int32): bool {
#pragma[magic: "LessOrEqualInt32", pure]
}
operator `>=`*(a, b: uint32): bool {
#pragma[magic: "GreaterOrEqualUInt32", pure]
}
operator `<=`*(a, b: uint32): bool {
#pragma[magic: "LessOrEqualUInt32", pure]
}
operator `>=`*(a, b: int16): bool {
#pragma[magic: "GreaterOrEqualInt16", pure]
}
operator `<=`*(a, b: int16): bool {
#pragma[magic: "LessOrEqualInt16", pure]
}
operator `>=`*(a, b: uint16): bool {
#pragma[magic: "GreaterOrEqualUInt16", pure]
}
operator `<=`*(a, b: uint16): bool {
#pragma[magic: "LessOrEqualUInt16", pure]
}
operator `>=`*(a, b: int8): bool {
#pragma[magic: "GreaterOrEqualInt8", pure]
}
operator `<=`*(a, b: int8): bool {
#pragma[magic: "LessOrEqualInt8", pure]
}
operator `>=`*(a, b: uint8): bool {
#pragma[magic: "GreaterOrEqualUInt8", pure]
}
operator `<=`*(a, b: uint8): bool {
#pragma[magic: "LessOrEqualUInt8", pure]
}
operator `>=`*(a, b: float): bool {
#pragma[magic: "GreaterOrEqualFloat64", pure]
}
operator `<=`*(a, b: float): bool {
#pragma[magic: "LessOrEqualFloat64", pure]
}
operator `>=`*(a, b: float32): bool {
#pragma[magic: "GreaterOrEqualFloat32", pure]
}
operator `<=`*(a, b: float32): bool {
#pragma[magic: "LessOrEqualFloat32", pure]
}
# Assignment operator
# TODO
#operator `=`[T](a: var T, b: T) {