Initial work on a stdlib of sorts, added comparison operators and refactored tests

This commit is contained in:
Mattia Giambirtone 2022-08-15 19:07:06 +02:00
parent 7c8ec4bc6c
commit 0861135e7f
14 changed files with 741 additions and 66 deletions

View File

@ -598,6 +598,84 @@ proc dispatch*(self: PeonVM) =
self.push(PeonObject(kind: Float32, halfFloat: -self.pop().halfFloat))
of LessThanInt64:
self.push(PeonObject(kind: Bool, boolean: self.pop().long < self.pop().long))
of GreaterThanInt64:
self.push(PeonObject(kind: Bool, boolean: self.pop().long > self.pop().long))
of EqualInt64:
self.push(PeonObject(kind: Bool, boolean: self.pop().long == self.pop().long))
of NotEqualInt64:
self.push(PeonObject(kind: Bool, boolean: self.pop().long != self.pop().long))
of LessThanUInt64:
self.push(PeonObject(kind: Bool, boolean: self.pop().long < self.pop().long))
of GreaterThanUInt64:
self.push(PeonObject(kind: Bool, boolean: self.pop().long > self.pop().long))
of EqualUInt64:
self.push(PeonObject(kind: Bool, boolean: self.pop().long == self.pop().long))
of NotEqualUInt64:
self.push(PeonObject(kind: Bool, boolean: self.pop().long != self.pop().long))
of LessThanInt32:
self.push(PeonObject(kind: Bool, boolean: self.pop().`int` < self.pop().`int`))
of GreaterThanInt32:
self.push(PeonObject(kind: Bool, boolean: self.pop().`int` > self.pop().`int`))
of EqualInt32:
self.push(PeonObject(kind: Bool, boolean: self.pop().`int` == self.pop().`int`))
of NotEqualInt32:
self.push(PeonObject(kind: Bool, boolean: self.pop().`int` != self.pop().`int`))
of LessThanUInt32:
self.push(PeonObject(kind: Bool, boolean: self.pop().uInt < self.pop().uInt))
of GreaterThanUInt32:
self.push(PeonObject(kind: Bool, boolean: self.pop().uInt > self.pop().uInt))
of EqualUInt32:
self.push(PeonObject(kind: Bool, boolean: self.pop().uInt == self.pop().uInt))
of NotEqualUInt32:
self.push(PeonObject(kind: Bool, boolean: self.pop().long != self.pop().long))
of LessThanInt16:
self.push(PeonObject(kind: Bool, boolean: self.pop().short < self.pop().short))
of GreaterThanInt16:
self.push(PeonObject(kind: Bool, boolean: self.pop().short > self.pop().short))
of EqualInt16:
self.push(PeonObject(kind: Bool, boolean: self.pop().short == self.pop().short))
of NotEqualInt16:
self.push(PeonObject(kind: Bool, boolean: self.pop().short != self.pop().short))
of LessThanUInt16:
self.push(PeonObject(kind: Bool, boolean: self.pop().uShort < self.pop().uShort))
of GreaterThanUInt16:
self.push(PeonObject(kind: Bool, boolean: self.pop().uShort > self.pop().uShort))
of EqualUInt16:
self.push(PeonObject(kind: Bool, boolean: self.pop().uShort == self.pop().uShort))
of NotEqualUInt16:
self.push(PeonObject(kind: Bool, boolean: self.pop().uShort != self.pop().uShort))
of LessThanInt8:
self.push(PeonObject(kind: Bool, boolean: self.pop().tiny < self.pop().tiny))
of GreaterThanInt8:
self.push(PeonObject(kind: Bool, boolean: self.pop().tiny > self.pop().tiny))
of EqualInt8:
self.push(PeonObject(kind: Bool, boolean: self.pop().tiny == self.pop().tiny))
of NotEqualInt8:
self.push(PeonObject(kind: Bool, boolean: self.pop().tiny != self.pop().tiny))
of LessThanUInt8:
self.push(PeonObject(kind: Bool, boolean: self.pop().uTiny < self.pop().uTiny))
of GreaterThanUInt8:
self.push(PeonObject(kind: Bool, boolean: self.pop().uTiny > self.pop().uTiny))
of EqualUInt8:
self.push(PeonObject(kind: Bool, boolean: self.pop().uTiny == self.pop().uTiny))
of NotEqualUInt8:
self.push(PeonObject(kind: Bool, boolean: self.pop().uTiny != self.pop().uTiny))
of LessThanFloat64:
self.push(PeonObject(kind: Bool, boolean: self.pop().`float` < self.pop().`float`))
of GreaterThanFloat64:
self.push(PeonObject(kind: Bool, boolean: self.pop().`float` > self.pop().`float`))
of EqualFloat64:
self.push(PeonObject(kind: Bool, boolean: self.pop().`float` == self.pop().`float`))
of NotEqualFLoat64:
self.push(PeonObject(kind: Bool, boolean: self.pop().`float` != self.pop().`float`))
of LessThanFloat32:
self.push(PeonObject(kind: Bool, boolean: self.pop().halfFloat < self.pop().halfFloat))
of GreaterThanFloat32:
self.push(PeonObject(kind: Bool, boolean: self.pop().halfFloat > self.pop().halfFloat))
of EqualFloat32:
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 SysClock64:
# Pushes the value of a monotonic clock
# as a 64 bit float onto the operand stack.

View File

@ -1025,6 +1025,84 @@ proc handleBuiltinFunction(self: Compiler, fn: Name, args: seq[Expression]) =
self.patchJump(jump)
of "LessThanInt64":
self.emitByte(LessThanInt64)
of "GreaterThanInt64":
self.emitByte(GreaterThanInt64)
of "EqualInt64":
self.emitByte(EqualInt64)
of "NotEqualInt64":
self.emitByte(NotEqualInt64)
of "LessThanUInt64":
self.emitByte(LessThanUInt64)
of "GreaterThanUInt64":
self.emitByte(GreaterThanUInt64)
of "EqualUInt64":
self.emitByte(EqualUInt64)
of "NotEqualUInt64":
self.emitByte(NotEqualUInt64)
of "LessThanInt32":
self.emitByte(LessThanInt32)
of "GreaterThanInt32":
self.emitByte(GreaterThanInt32)
of "EqualInt32":
self.emitByte(EqualInt32)
of "NotEqualInt32":
self.emitByte(NotEqualInt32)
of "LessThanUInt32":
self.emitByte(LessThanUInt32)
of "GreaterThanUInt32":
self.emitByte(GreaterThanUInt32)
of "EqualUInt32":
self.emitByte(EqualUInt32)
of "NotEqualUInt32":
self.emitByte(NotEqualUInt32)
of "LessThanInt16":
self.emitByte(LessThanInt16)
of "GreaterThanInt16":
self.emitByte(GreaterThanInt16)
of "EqualInt16":
self.emitByte(EqualInt16)
of "NotEqualInt16":
self.emitByte(NotEqualInt16)
of "LessThanUInt16":
self.emitByte(LessThanUInt16)
of "GreaterThanUInt16":
self.emitByte(GreaterThanUInt16)
of "EqualUInt16":
self.emitByte(EqualUInt16)
of "NotEqualUInt16":
self.emitByte(NotEqualUInt16)
of "LessThanInt8":
self.emitByte(LessThanInt8)
of "GreaterThanInt8":
self.emitByte(GreaterThanInt8)
of "EqualInt8":
self.emitByte(EqualInt8)
of "NotEqualInt8":
self.emitByte(NotEqualInt8)
of "LessThanUInt8":
self.emitByte(LessThanInt64)
of "GreaterThanUInt8":
self.emitByte(GreaterThanUInt8)
of "EqualUInt8":
self.emitByte(EqualUInt8)
of "NotEqualUInt8":
self.emitByte(NotEqualUInt8)
of "LessThanFloat64":
self.emitByte(LessThanFloat64)
of "GreaterThanFloat64":
self.emitByte(GreaterThanFloat64)
of "EqualFloat64":
self.emitByte(EqualFloat64)
of "NotEqualFloat64":
self.emitByte(NotEqualFloat64)
of "LessThanFloat32":
self.emitByte(LessThanFloat32)
of "GreaterThanFloat32":
self.emitByte(GreaterThanFloat32)
of "EqualFloat32":
self.emitByte(EqualFloat32)
of "NotEqualFloat32":
self.emitByte(NotEqualFloat32)
of "SysClock64":
self.emitByte(SysClock64)
else:
@ -1184,7 +1262,8 @@ proc declareName(self: Compiler, node: Declaration, mutable: bool = false) =
name.valueType = self.inferType(argument.valueType)
# If it's still nil, it's an error!
if name.valueType.isNil():
self.error(&"cannot determine the type of argument '{argument.name.token.lexeme}'")
echo argument.name.token
self.error(&"cannot determine the type of argument '{argument.name.token.lexeme}'", argument.name)
fn.valueType.args.add((argument.name.token.lexeme, name.valueType))
else:
discard # TODO: Types, enums

View File

@ -237,6 +237,7 @@ 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)

View File

@ -138,6 +138,45 @@ type
DivFloat32,
MulFloat32,
LessThanInt64,
GreaterThanInt64,
EqualInt64,
NotEqualInt64,
LessThanUInt64,
GreaterThanUInt64,
EqualUInt64,
NotEqualUInt64,
LessThanInt32,
GreaterThanInt32,
EqualInt32,
NotEqualInt32,
LessThanUInt32,
GreaterThanUInt32,
EqualUInt32,
NotEqualUInt32,
LessThanInt16,
GreaterThanInt16,
EqualInt16,
NotEqualInt16,
LessThanUInt16,
GreaterThanUInt16,
EqualUInt16,
NotEqualUInt16,
LessThanInt8,
GreaterThanInt8,
EqualInt8,
NotEqualInt8,
LessThanUInt8,
GreaterThanUInt8,
EqualUInt8,
NotEqualUInt8,
LessThanFloat64,
GreaterThanFloat64,
EqualFloat64,
NotEqualFloat64,
LessThanFloat32,
GreaterThanFloat32,
EqualFloat32,
NotEqualFloat32,
SysClock64,
## Basic stack operations
Pop, # Pops an element off the stack and discards it
@ -201,6 +240,19 @@ const simpleInstructions* = {Return, LoadNil,
AddFloat32, SubFloat32, DivFloat32,
MulFloat32, NegFloat32, NegFloat64,
LessThanInt64, SysClock64, GenericPrint,
GreaterThanInt64, EqualInt64, NotEqualInt64,
LessThanUInt64, GreaterThanUInt64, EqualUInt64,
NotEqualUInt64, LessThanInt32, GreaterThanInt32,
EqualInt32, NotEqualInt32, LessThanUInt32,
GreaterThanUInt32, EqualUInt32, NotEqualUInt32,
LessThanInt16, GreaterThanInt16, EqualInt16,
NotEqualInt16, LessThanUInt16, GreaterThanUInt16,
EqualUInt16, NotEqualUInt16, LessThanInt8,
GreaterThanInt8,EqualInt8, NotEqualInt8,
LessThanUInt8, GreaterThanUInt8, EqualUInt8,
NotEqualUInt8, LessThanFloat64, GreaterThanFloat64,
EqualFloat64,NotEqualFloat64, LessThanFloat32,
GreaterThanFloat32, EqualFloat32, NotEqualFloat32,
}
# Constant instructions are instructions that operate on the bytecode constant table

View File

@ -119,7 +119,7 @@ proc addOperator(self: OperatorTable, lexeme: string) =
var prec = Precedence.high()
if lexeme.len() >= 2 and lexeme[^2..^1] in ["->", "~>", "=>"]:
prec = Arrow
elif lexeme.endsWith("=") and lexeme[0] notin {'<', '>', '!', '?', '~', '='}:
elif lexeme.endsWith("=") and lexeme[0] notin {'<', '>', '!', '?', '~', '='} or lexeme == "=":
prec = Assign
elif lexeme[0] in {'$', } or lexeme == "**":
prec = Power
@ -409,6 +409,7 @@ proc makeCall(self: Parser, callee: Expression): CallExpr =
argument = self.expression()
if argument.kind == binaryExpr and BinaryExpr(argument).operator.lexeme == "=":
# TODO: This will explode with slices!
echo argument
if IdentExpr(BinaryExpr(argument).a) in argNames:
self.error("duplicate keyword argument in call")
argNames.add(IdentExpr(BinaryExpr(argument).a))

View File

@ -170,6 +170,8 @@ proc constantInstruction(self: Debugger, instruction: OpCode) =
self.current += 4
if instruction == LoadString:
stdout.styledWriteLine(fgGreen, " of length ", fgYellow, $size)
else:
stdout.write("\n")
proc jumpInstruction(self: Debugger, instruction: OpCode) =

63
src/util/symbols.nim Normal file
View File

@ -0,0 +1,63 @@
import ../frontend/lexer
proc fillSymbolTable*(tokenizer: Lexer) =
## Initializes the Lexer's symbol
## table with the builtin symbols
## and keywords
# 1-byte symbols
tokenizer.symbols.addSymbol("{", LeftBrace)
tokenizer.symbols.addSymbol("}", RightBrace)
tokenizer.symbols.addSymbol("(", LeftParen)
tokenizer.symbols.addSymbol(")", RightParen)
tokenizer.symbols.addSymbol("[", LeftBracket)
tokenizer.symbols.addSymbol("]", RightBracket)
tokenizer.symbols.addSymbol(".", Dot)
tokenizer.symbols.addSymbol(",", Comma)
tokenizer.symbols.addSymbol(";", Semicolon)
# tokenizer.symbols.addSymbol("\n", Semicolon) # TODO: Broken
# Keywords
tokenizer.symbols.addKeyword("type", TokenType.Type)
tokenizer.symbols.addKeyword("enum", Enum)
tokenizer.symbols.addKeyword("case", Case)
tokenizer.symbols.addKeyword("operator", Operator)
tokenizer.symbols.addKeyword("generator", Generator)
tokenizer.symbols.addKeyword("fn", TokenType.Function)
tokenizer.symbols.addKeyword("coroutine", Coroutine)
tokenizer.symbols.addKeyword("break", TokenType.Break)
tokenizer.symbols.addKeyword("continue", Continue)
tokenizer.symbols.addKeyword("while", While)
tokenizer.symbols.addKeyword("for", For)
tokenizer.symbols.addKeyword("foreach", Foreach)
tokenizer.symbols.addKeyword("if", If)
tokenizer.symbols.addKeyword("else", Else)
tokenizer.symbols.addKeyword("await", TokenType.Await)
tokenizer.symbols.addKeyword("defer", Defer)
tokenizer.symbols.addKeyword("try", Try)
tokenizer.symbols.addKeyword("except", Except)
tokenizer.symbols.addKeyword("finally", Finally)
tokenizer.symbols.addKeyword("raise", TokenType.Raise)
tokenizer.symbols.addKeyword("assert", TokenType.Assert)
tokenizer.symbols.addKeyword("const", Const)
tokenizer.symbols.addKeyword("let", Let)
tokenizer.symbols.addKeyword("var", TokenType.Var)
tokenizer.symbols.addKeyword("import", Import)
tokenizer.symbols.addKeyword("yield", TokenType.Yield)
tokenizer.symbols.addKeyword("return", TokenType.Return)
tokenizer.symbols.addKeyword("object", Object)
# These are more like expressions with a reserved
# name that produce a value of a builtin type,
# but we don't need to care about that until
# we're in the parsing/ compilation steps so
# it's fine
tokenizer.symbols.addKeyword("nan", NotANumber)
tokenizer.symbols.addKeyword("inf", Infinity)
tokenizer.symbols.addKeyword("nil", TokenType.Nil)
tokenizer.symbols.addKeyword("true", True)
tokenizer.symbols.addKeyword("false", False)
tokenizer.symbols.addKeyword("ref", TokenType.Ref)
tokenizer.symbols.addKeyword("ptr", TokenType.Ptr)
for sym in [">", "<", "=", "~", "/", "+", "-", "_", "*", "?", "@", ":", "==", "!=",
">=", "<=", "+=", "-=", "/=", "*=", "**=", "!"]:
tokenizer.symbols.addSymbol(sym, Symbol)

7
tests/comparisons.pn Normal file
View File

@ -0,0 +1,7 @@
import std;
print(3 > 2); # true
print(2 < 3); # false
print(2 == 3); # false
print(2 != 3); # true

View File

@ -1,4 +1,4 @@
import lib;
import std;
fn fib(n: int): int {
@ -13,4 +13,4 @@ print("Computing the value of fib(25)");
var x = clock();
print(fib(25));
print(clock() - x);
print("Done!");
print("Done!");

View File

@ -1,43 +0,0 @@
operator `<`*(a, b: int): bool {
#pragma[magic: "LessThanInt64", pure]
}
operator `-`*(a, b: float): float {
#pragma[magic: "SubFloat64", pure]
}
operator `-`*(a, b: int): int {
#pragma[magic: "SubInt64", pure]
}
operator `+`*(a, b: int): int {
#pragma[magic: "AddInt64", pure]
}
operator `/`*(a, b: int): int {
#pragma[magic: "DivInt64", pure]
}
fn clock*: float {
#pragma[magic: "SysClock64", pure]
}
fn print*(x: float) {
#pragma[magic: "GenericPrint"]
}
fn print*(x: int) {
#pragma[magic: "GenericPrint"]
}
fn print*(x: string) {
#pragma[magic: "GenericPrint"]
}

View File

@ -1,6 +0,0 @@
operator `<`(a, b: int): bool {#pragma[magic: "LessThanInt64", pure]}
operator `>`(a, b: int): bool {return b < a;}
3 > 2;
2 < 3;

View File

@ -1,24 +1,18 @@
operator `=`[T](a: var T, b: T) {
#pragma[magic: "GenericAssign"]
}
import std;
operator `+`(a, b: int): int {
#pragma[magic: "AddInt64", pure]
}
operator `+=`(a: var int, b: int) {
a = a + b;
}
fn identity(x: var int): int {
fn plusOne(x: var int): int {
x += 1;
return x;
}
var x = 5;
identity(x);
# identity(38); # If you uncomment this, the compiler errors out!
print(plusOne(x));
# plusOne(38); # If you uncomment this, the compiler errors out!

View File

@ -1,10 +1,13 @@
import std;
var x = 5;
{
var x = 55;
{
var x = 22;
x;
print(x);
}
x;
print(x);
}
x;
print(x);

444
tests/std.pn Normal file
View File

@ -0,0 +1,444 @@
## The peon standard library
# Builtin arithmetic operators for Peon
# Note: Most of these do nothing on their own. All they do
# is serve as placeholders for emitting specific VM
# instructions. They're implemented this way because:
# - They tie into the existing type system nicely
# - It makes the implementation easier and more flexible
operator `+`*(a, b: int): int {
#pragma[magic: "AddInt64", pure]
}
operator `+`*(a, b: uint64): uint64 {
#pragma[magic: "AddUInt64", pure]
}
operator `+`*(a, b: int32): int32 {
#pragma[magic: "AddInt32", pure]
}
operator `+`*(a, b: uint32): uint32 {
#pragma[magic: "AddUInt32", pure]
}
operator `+`*(a, b: int16): int16 {
#pragma[magic: "AddInt16", pure]
}
operator `+`*(a, b: uint16): uint16 {
#pragma[magic: "AddUInt16", pure]
}
operator `+`*(a, b: int8): int8 {
#pragma[magic: "AddInt8", pure]
}
operator `+`*(a, b: uint8): uint8 {
#pragma[magic: "AddUInt8", pure]
}
operator `+`*(a, b: float64): float64 {
#pragma[magic: "AddFloat64", pure]
}
operator `+`*(a, b: float32): float32 {
#pragma[magic: "AddFloat32", pure]
}
operator `-`*(a, b: int): int {
#pragma[magic: "SubInt64", pure]
}
operator `-`*(a, b: uint64): uint64 {
#pragma[magic: "SubUInt64", pure]
}
operator `-`*(a, b: int32): int32 {
#pragma[magic: "SubInt32", pure]
}
operator `-`*(a, b: uint32): uint32 {
#pragma[magic: "SubUInt32", pure]
}
operator `-`*(a, b: int16): int16 {
#pragma[magic: "SubInt16", pure]
}
operator `-`*(a, b: uint16): uint16 {
#pragma[magic: "SubUInt16", pure]
}
operator `-`*(a, b: int8): int8 {
#pragma[magic: "SubInt8", pure]
}
operator `-`*(a, b: uint8): uint8 {
#pragma[magic: "SubUInt8", pure]
}
operator `-`*(a, b: float64): float64 {
#pragma[magic: "SubFloat64", pure]
}
operator `-`*(a, b: float32): float32 {
#pragma[magic: "SubFloat32", pure]
}
operator `*`*(a, b: int): int {
#pragma[magic: "MulInt64", pure]
}
operator `*`*(a, b: uint64): uint64 {
#pragma[magic: "MulUInt64", pure]
}
operator `*`*(a, b: int32): int32 {
#pragma[magic: "MulInt32", pure]
}
operator `*`*(a, b: uint32): uint32 {
#pragma[magic: "MulUInt32", pure]
}
operator `*`*(a, b: int16): int16 {
#pragma[magic: "MulInt16", pure]
}
operator `*`*(a, b: uint16): uint16 {
#pragma[magic: "MulUInt16", pure]
}
operator `*`*(a, b: int8): int8 {
#pragma[magic: "MulInt8", pure]
}
operator `*`*(a, b: uint8): uint8 {
#pragma[magic: "MulUInt8", pure]
}
operator `*`*(a, b: float64): float64 {
#pragma[magic: "MulFloat64", pure]
}
operator `*`*(a, b: float32): float32 {
#pragma[magic: "MulFloat32", pure]
}
operator `/`*(a, b: int): int {
#pragma[magic: "DivInt64", pure]
}
operator `/`*(a, b: uint64): uint64 {
#pragma[magic: "DivUInt64", pure]
}
operator `/`*(a, b: int32): int32 {
#pragma[magic: "DivInt32", pure]
}
operator `/`*(a, b: uint32): uint32 {
#pragma[magic: "DivUInt32", pure]
}
operator `/`*(a, b: int16): int16 {
#pragma[magic: "DivInt16", pure]
}
operator `/`*(a, b: uint16): uint16 {
#pragma[magic: "DivUInt16", pure]
}
operator `/`*(a, b: int8): int8 {
#pragma[magic: "DivInt8", pure]
}
operator `/`*(a, b: uint8): uint8 {
#pragma[magic: "DivUInt8", pure]
}
operator `/`*(a, b: float64): float64 {
#pragma[magic: "DivFloat64", pure]
}
operator `/`*(a, b: float32): float32 {
#pragma[magic: "DivFloat32", pure]
}
# Comparison operators
operator `>`*(a, b: int): bool {
#pragma[magic: "GreaterThanInt64", pure]
}
operator `<`*(a, b: int): bool {
#pragma[magic: "LessThanInt64", pure]
}
operator `==`*(a, b: int): bool {
#pragma[magic: "EqualInt64", pure]
}
operator `!=`*(a, b: int): bool {
#pragma[magic: "NotEqualInt64", pure]
}
operator `>`*(a, b: uint64): bool {
#pragma[magic: "GreaterThanUInt64", pure]
}
operator `<`*(a, b: uint64): bool {
#pragma[magic: "LessThanUInt64", pure]
}
operator `==`*(a, b: uint64): bool {
#pragma[magic: "EqualUInt64", pure]
}
operator `!=`*(a, b: uint64): bool {
#pragma[magic: "NotEqualUInt64", pure]
}
operator `>`*(a, b: int32): bool {
#pragma[magic: "GreaterThanInt32", pure]
}
operator `<`*(a, b: int32): bool {
#pragma[magic: "LessThanInt32", pure]
}
operator `==`*(a, b: int32): bool {
#pragma[magic: "EqualInt32", pure]
}
operator `!=`*(a, b: int32): bool {
#pragma[magic: "NotEqualInt32", pure]
}
operator `>`*(a, b: uint32): bool {
#pragma[magic: "GreaterThanUInt32", pure]
}
operator `<`*(a, b: uint32): bool {
#pragma[magic: "LessThanUInt32", pure]
}
operator `==`*(a, b: uint32): bool {
#pragma[magic: "EqualUInt32", pure]
}
operator `!=`*(a, b: uint32): bool {
#pragma[magic: "NotEqualUInt32", pure]
}
operator `>`*(a, b: int16): bool {
#pragma[magic: "GreaterThanInt16", pure]
}
operator `<`*(a, b: int16): bool {
#pragma[magic: "LessThanInt16", pure]
}
operator `==`*(a, b: int16): bool {
#pragma[magic: "EqualInt16", pure]
}
operator `!=`*(a, b: int16): bool {
#pragma[magic: "NotEqualInt16", pure]
}
operator `>`*(a, b: uint16): bool {
#pragma[magic: "GreaterThanUInt16", pure]
}
operator `<`*(a, b: uint16): bool {
#pragma[magic: "LessThanUInt16", pure]
}
operator `==`*(a, b: uint16): bool {
#pragma[magic: "EqualUInt16", pure]
}
operator `!=`*(a, b: uint16): bool {
#pragma[magic: "NotEqualUInt16", pure]
}
operator `>`*(a, b: int8): bool {
#pragma[magic: "GreaterThanInt8", pure]
}
operator `<`*(a, b: int8): bool {
#pragma[magic: "LessThanInt8", pure]
}
operator `==`*(a, b: int8): bool {
#pragma[magic: "EqualInt8", pure]
}
operator `!=`*(a, b: int8): bool {
#pragma[magic: "NotEqualInt8", pure]
}
operator `>`*(a, b: uint8): bool {
#pragma[magic: "GreaterThanUInt8", pure]
}
operator `<`*(a, b: uint8): bool {
#pragma[magic: "LessThanUInt8", pure]
}
operator `==`*(a, b: uint8): bool {
#pragma[magic: "EqualUInt8", pure]
}
operator `!=`*(a, b: uint8): bool {
#pragma[magic: "NotEqualUInt8", pure]
}
operator `>`*(a, b: float): bool {
#pragma[magic: "GreaterThanFloat64", pure]
}
operator `<`*(a, b: float): bool {
#pragma[magic: "LessThanFloat64", pure]
}
operator `==`*(a, b: float): bool {
#pragma[magic: "EqualFloat64", pure]
}
operator `!=`*(a, b: float): bool {
#pragma[magic: "NotEqualFloat64", pure]
}
operator `>`*(a, b: float32): bool {
#pragma[magic: "GreaterThanFloat32", pure]
}
operator `<`*(a, b: float32): bool {
#pragma[magic: "LessThanFloat32", pure]
}
operator `==`*(a, b: float32): bool {
#pragma[magic: "EqualFloat32", pure]
}
operator `!=`*(a, b: float32): bool {
#pragma[magic: "NotEqualFloat32", pure]
}
# Assignment operator
# TODO
#operator `=`[T](a: var T, b: T) {
# #pragma[magic: "GenericAssign"]
#}
# Some useful builtins
fn clock*: float {
#pragma[magic: "SysClock64", pure]
}
# TODO: Replace with generics
fn print*(x: float) {
#pragma[magic: "GenericPrint"]
}
fn print*(x: int) {
#pragma[magic: "GenericPrint"]
}
fn print*(x: string) {
#pragma[magic: "GenericPrint"]
}
fn print*(x: bool) {
#pragma[magic: "GenericPrint"]
}