diff --git a/src/backend/vm.nim b/src/backend/vm.nim index 8df9989..59803e5 100644 --- a/src/backend/vm.nim +++ b/src/backend/vm.nim @@ -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. diff --git a/src/frontend/compiler.nim b/src/frontend/compiler.nim index 67e9bc6..3cbd023 100644 --- a/src/frontend/compiler.nim +++ b/src/frontend/compiler.nim @@ -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 diff --git a/src/frontend/lexer.nim b/src/frontend/lexer.nim index c72cb89..6ff1045 100644 --- a/src/frontend/lexer.nim +++ b/src/frontend/lexer.nim @@ -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) diff --git a/src/frontend/meta/bytecode.nim b/src/frontend/meta/bytecode.nim index b12d2e5..a5642bf 100644 --- a/src/frontend/meta/bytecode.nim +++ b/src/frontend/meta/bytecode.nim @@ -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 diff --git a/src/frontend/parser.nim b/src/frontend/parser.nim index ebd4ee4..3dc1165 100644 --- a/src/frontend/parser.nim +++ b/src/frontend/parser.nim @@ -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)) diff --git a/src/util/debugger.nim b/src/util/debugger.nim index 0592585..63d0589 100644 --- a/src/util/debugger.nim +++ b/src/util/debugger.nim @@ -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) = diff --git a/src/util/symbols.nim b/src/util/symbols.nim new file mode 100644 index 0000000..c7f2dca --- /dev/null +++ b/src/util/symbols.nim @@ -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) \ No newline at end of file diff --git a/tests/comparisons.pn b/tests/comparisons.pn new file mode 100644 index 0000000..48681e2 --- /dev/null +++ b/tests/comparisons.pn @@ -0,0 +1,7 @@ +import std; + + +print(3 > 2); # true +print(2 < 3); # false +print(2 == 3); # false +print(2 != 3); # true diff --git a/tests/import/fib.pn b/tests/fib.pn similarity index 87% rename from tests/import/fib.pn rename to tests/fib.pn index b44f054..77e466d 100644 --- a/tests/import/fib.pn +++ b/tests/fib.pn @@ -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!"); \ No newline at end of file +print("Done!"); diff --git a/tests/import/lib.pn b/tests/import/lib.pn deleted file mode 100644 index bcb3b10..0000000 --- a/tests/import/lib.pn +++ /dev/null @@ -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"] -} diff --git a/tests/lt_gt.pn b/tests/lt_gt.pn deleted file mode 100644 index 6049f38..0000000 --- a/tests/lt_gt.pn +++ /dev/null @@ -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; diff --git a/tests/mutable.pn b/tests/mutable.pn index 86a6bee..e0efb09 100644 --- a/tests/mutable.pn +++ b/tests/mutable.pn @@ -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! diff --git a/tests/scopes.pn b/tests/scopes.pn index 1a66e00..fe7e604 100644 --- a/tests/scopes.pn +++ b/tests/scopes.pn @@ -1,10 +1,13 @@ +import std; + + var x = 5; { var x = 55; { var x = 22; - x; + print(x); } - x; + print(x); } -x; \ No newline at end of file +print(x); \ No newline at end of file diff --git a/tests/std.pn b/tests/std.pn new file mode 100644 index 0000000..8bd24dc --- /dev/null +++ b/tests/std.pn @@ -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"] +} \ No newline at end of file