Initial ground work on generics, some stuff is broken :(
This commit is contained in:
parent
d4d1034cef
commit
8667cbdceb
|
@ -413,6 +413,7 @@ proc patchJump(self: Compiler, offset: int) =
|
||||||
if jump < 0:
|
if jump < 0:
|
||||||
self.error("invalid jump size (< 0), did the bytecode size change without fixJumps being called?")
|
self.error("invalid jump size (< 0), did the bytecode size change without fixJumps being called?")
|
||||||
if jump > 16777215:
|
if jump > 16777215:
|
||||||
|
# TODO: Emit consecutive jumps?
|
||||||
self.error("cannot jump more than 16777215 instructions")
|
self.error("cannot jump more than 16777215 instructions")
|
||||||
self.setJump(self.jumps[offset].offset, (jump - 4).toTriple())
|
self.setJump(self.jumps[offset].offset, (jump - 4).toTriple())
|
||||||
self.jumps[offset].patched = true
|
self.jumps[offset].patched = true
|
||||||
|
@ -493,8 +494,43 @@ proc resolve(self: Compiler, name: IdentExpr,
|
||||||
self.varDecl(VarDecl(obj.node), obj)
|
self.varDecl(VarDecl(obj.node), obj)
|
||||||
of NameKind.Type:
|
of NameKind.Type:
|
||||||
self.typeDecl(TypeDecl(obj.node), obj)
|
self.typeDecl(TypeDecl(obj.node), obj)
|
||||||
|
of NameKind.Function:
|
||||||
|
if not obj.valueType.isGeneric:
|
||||||
|
self.funDecl(FunDecl(obj.node), obj)
|
||||||
|
# Generic functions need to be compiled at
|
||||||
|
# the call site, but regular functions can
|
||||||
|
# be precompiled as soon as we resolve them
|
||||||
else:
|
else:
|
||||||
discard # Functions need to be compiled at the call site
|
discard
|
||||||
|
return obj
|
||||||
|
return nil
|
||||||
|
|
||||||
|
|
||||||
|
proc resolve(self: Compiler, name: string,
|
||||||
|
depth: int = self.scopeDepth): Name =
|
||||||
|
## Version of resolve that takes strings instead
|
||||||
|
## of AST nodes
|
||||||
|
for obj in reversed(self.names):
|
||||||
|
if obj.name.token.lexeme == name:
|
||||||
|
if obj.isPrivate and obj.owner != self.currentModule:
|
||||||
|
continue # There may be a name in the current module that
|
||||||
|
# matches, so we skip this
|
||||||
|
if not obj.resolved:
|
||||||
|
obj.resolved = true
|
||||||
|
obj.codePos = self.chunk.code.len()
|
||||||
|
case obj.kind:
|
||||||
|
of NameKind.Var:
|
||||||
|
self.varDecl(VarDecl(obj.node), obj)
|
||||||
|
of NameKind.Type:
|
||||||
|
self.typeDecl(TypeDecl(obj.node), obj)
|
||||||
|
of NameKind.Function:
|
||||||
|
if not obj.valueType.isGeneric:
|
||||||
|
self.funDecl(FunDecl(obj.node), obj)
|
||||||
|
# Generic functions need to be compiled at
|
||||||
|
# the call site, but regular functions can
|
||||||
|
# be precompiled as soon as we resolve them
|
||||||
|
else:
|
||||||
|
discard
|
||||||
return obj
|
return obj
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
|
@ -509,6 +545,8 @@ proc getStackPos(self: Compiler, name: Name): int =
|
||||||
continue
|
continue
|
||||||
elif not variable.belongsTo.isNil() and variable.belongsTo.valueType.isBuiltinFunction:
|
elif not variable.belongsTo.isNil() and variable.belongsTo.valueType.isBuiltinFunction:
|
||||||
continue
|
continue
|
||||||
|
elif not variable.valueType.isNil() and variable.valueType.kind == Generic:
|
||||||
|
continue
|
||||||
if name == variable:
|
if name == variable:
|
||||||
found = true
|
found = true
|
||||||
break
|
break
|
||||||
|
@ -722,11 +760,18 @@ proc infer(self: Compiler, node: Expression): Type =
|
||||||
case node.kind:
|
case node.kind:
|
||||||
of identExpr:
|
of identExpr:
|
||||||
let node = IdentExpr(node)
|
let node = IdentExpr(node)
|
||||||
let name = self.resolve(node)
|
var name = self.resolve(node)
|
||||||
if not name.isNil():
|
if not name.isNil():
|
||||||
result = name.valueType
|
result = name.valueType
|
||||||
if result.kind == Generic:
|
if not result.isNil() and result.kind == Generic:
|
||||||
result = self.resolve(newIdentExpr(Token(lexeme: result.name, kind: Identifier))).valueType
|
if name.belongsTo.isNil():
|
||||||
|
name = self.resolve(result.name)
|
||||||
|
if not name.isNil():
|
||||||
|
return name.valueType
|
||||||
|
else:
|
||||||
|
for arg in name.belongsTo.valueType.args:
|
||||||
|
if node.token.lexeme == arg.name:
|
||||||
|
return arg.kind
|
||||||
else:
|
else:
|
||||||
result = node.name.lexeme.toIntrinsic()
|
result = node.name.lexeme.toIntrinsic()
|
||||||
of unaryExpr:
|
of unaryExpr:
|
||||||
|
@ -886,7 +931,7 @@ proc check(self: Compiler, term: Expression, kind: Type, allowAny: bool = false)
|
||||||
## otherwise
|
## otherwise
|
||||||
let k = self.infer(term)
|
let k = self.infer(term)
|
||||||
if k.isNil():
|
if k.isNil():
|
||||||
if term.kind == identExpr:
|
if term.kind == identExpr and self.resolve(IdentExpr(term)).isNil():
|
||||||
self.error(&"reference to undeclared name '{term.token.lexeme}'", term)
|
self.error(&"reference to undeclared name '{term.token.lexeme}'", term)
|
||||||
elif term.kind == callExpr and CallExpr(term).callee.kind == identExpr:
|
elif term.kind == callExpr and CallExpr(term).callee.kind == identExpr:
|
||||||
self.error(&"call to undeclared function '{CallExpr(term).callee.token.lexeme}'", term)
|
self.error(&"call to undeclared function '{CallExpr(term).callee.token.lexeme}'", term)
|
||||||
|
@ -1011,7 +1056,10 @@ proc endScope(self: Compiler) =
|
||||||
for name in self.names:
|
for name in self.names:
|
||||||
if name.depth > self.scopeDepth:
|
if name.depth > self.scopeDepth:
|
||||||
names.add(name)
|
names.add(name)
|
||||||
if name.kind in [NameKind.Var, NameKind.Argument]:
|
if not name.resolved:
|
||||||
|
# TODO: Emit a warning?
|
||||||
|
continue
|
||||||
|
elif name.kind in [NameKind.Var, NameKind.Argument]:
|
||||||
# We don't increase the pop count for some kinds of objects
|
# We don't increase the pop count for some kinds of objects
|
||||||
# because they're not stored the same way as regular variables
|
# because they're not stored the same way as regular variables
|
||||||
# (for types, generics and function declarations)
|
# (for types, generics and function declarations)
|
||||||
|
@ -1211,6 +1259,7 @@ proc emitLoop(self: Compiler, begin: int, line: int) =
|
||||||
## jump offset
|
## jump offset
|
||||||
let offset = self.chunk.code.high() - begin + 4
|
let offset = self.chunk.code.high() - begin + 4
|
||||||
if offset > 16777215:
|
if offset > 16777215:
|
||||||
|
# TODO: Emit consecutive jumps?
|
||||||
self.error("cannot jump more than 16777215 bytecode instructions")
|
self.error("cannot jump more than 16777215 bytecode instructions")
|
||||||
self.emitByte(JumpBackwards, line)
|
self.emitByte(JumpBackwards, line)
|
||||||
self.emitBytes(offset.toTriple(), line)
|
self.emitBytes(offset.toTriple(), line)
|
||||||
|
@ -1625,31 +1674,40 @@ proc generateCall(self: Compiler, fn: Name, args: seq[Expression], line: int) =
|
||||||
self.patchReturnAddress(pos)
|
self.patchReturnAddress(pos)
|
||||||
|
|
||||||
|
|
||||||
proc shadowGenerics(self: Compiler, fn: Name, args: seq[Expression]) =
|
proc specializeGeneric(self: Compiler, fn: Name, args: seq[Expression]): Name =
|
||||||
## Specializes a generic function by
|
## Specializes a generic function by
|
||||||
## shadowing the names of the generic
|
## instantiating a concrete version
|
||||||
## types with their respective concrete
|
## of it
|
||||||
## types
|
|
||||||
var mapping: TableRef[string, Type] = newTable[string, Type]()
|
var mapping: TableRef[string, Type] = newTable[string, Type]()
|
||||||
var kind: Type
|
var kind: Type
|
||||||
|
result = deepCopy(fn)
|
||||||
# This first loop checks if a user tries to reassign a generic's
|
# This first loop checks if a user tries to reassign a generic's
|
||||||
# name to a different type
|
# name to a different type
|
||||||
for i, (name, typ) in fn.valueType.args:
|
for i, (name, typ) in result.valueType.args:
|
||||||
if typ.kind != Generic:
|
if typ.kind != Generic:
|
||||||
continue
|
continue
|
||||||
kind = self.infer(args[i])
|
kind = self.infer(args[i])
|
||||||
if typ.name in mapping and not self.compare(kind, mapping[typ.name]):
|
if typ.name in mapping and not self.compare(kind, mapping[typ.name]):
|
||||||
self.error(&"expected generic argument '{typ.name}' to be of type {self.typeToStr(mapping[typ.name])}, got {self.typeToStr(kind)} instead")
|
self.error(&"expected generic argument '{typ.name}' to be of type {self.typeToStr(mapping[typ.name])}, got {self.typeToStr(kind)} instead")
|
||||||
mapping[typ.name] = kind
|
mapping[typ.name] = kind
|
||||||
for gen in mapping.keys():
|
result.valueType.args[i].kind = kind
|
||||||
kind = mapping[gen]
|
for (argExpr, argName) in zip(args, result.valueType.args):
|
||||||
|
if self.names.high() > 16777215:
|
||||||
|
self.error("cannot declare more than 16777215 variables at a time")
|
||||||
self.names.add(Name(depth: self.scopeDepth + 1,
|
self.names.add(Name(depth: self.scopeDepth + 1,
|
||||||
isPrivate: true,
|
isPrivate: true,
|
||||||
isConst: false,
|
|
||||||
owner: self.currentModule,
|
owner: self.currentModule,
|
||||||
|
isConst: false,
|
||||||
|
name: newIdentExpr(Token(lexeme: argName.name)),
|
||||||
|
valueType: argName.kind,
|
||||||
|
codePos: 0,
|
||||||
|
isLet: false,
|
||||||
line: fn.line,
|
line: fn.line,
|
||||||
valueType: kind,
|
belongsTo: result,
|
||||||
name: newIdentExpr(Token(kind: TokenType.Identifier, lexeme: gen))))
|
kind: NameKind.Argument
|
||||||
|
))
|
||||||
|
if result.valueType.returnType.kind == Generic:
|
||||||
|
result.valueType.returnType = mapping[result.valueType.returnType.name]
|
||||||
|
|
||||||
|
|
||||||
proc callExpr(self: Compiler, node: CallExpr): Name {.discardable.} =
|
proc callExpr(self: Compiler, node: CallExpr): Name {.discardable.} =
|
||||||
|
@ -1663,7 +1721,7 @@ proc callExpr(self: Compiler, node: CallExpr): Name {.discardable.} =
|
||||||
dec(i)
|
dec(i)
|
||||||
kind = self.infer(argument)
|
kind = self.infer(argument)
|
||||||
if kind.isNil():
|
if kind.isNil():
|
||||||
if argument.kind == identExpr:
|
if argument.kind == identExpr and self.resolve(IdentExpr(argument)).isNil():
|
||||||
self.error(&"reference to undeclared name '{IdentExpr(argument).name.lexeme}'")
|
self.error(&"reference to undeclared name '{IdentExpr(argument).name.lexeme}'")
|
||||||
if node.callee.kind != identExpr:
|
if node.callee.kind != identExpr:
|
||||||
self.error(&"cannot infer the type of argument {i + 1} in call")
|
self.error(&"cannot infer the type of argument {i + 1} in call")
|
||||||
|
@ -1676,9 +1734,13 @@ proc callExpr(self: Compiler, node: CallExpr): Name {.discardable.} =
|
||||||
# Calls like hi()
|
# Calls like hi()
|
||||||
result = self.matchImpl(IdentExpr(node.callee).name.lexeme, Type(kind: Function, returnType: Type(kind: Any), args: args), node)
|
result = self.matchImpl(IdentExpr(node.callee).name.lexeme, Type(kind: Function, returnType: Type(kind: Any), args: args), node)
|
||||||
if result.valueType.isGeneric:
|
if result.valueType.isGeneric:
|
||||||
self.shadowGenerics(result, argExpr)
|
result = self.specializeGeneric(result, argExpr)
|
||||||
# Here is when the function gets *actually* compiled
|
# We can't instantiate a concrete version
|
||||||
self.funDecl(FunDecl(result.node), result)
|
# of a generic function without the types
|
||||||
|
# of its arguments, so we wait until the
|
||||||
|
# very last moment to compile it, once
|
||||||
|
# that info is available to us
|
||||||
|
self.funDecl(FunDecl(result.node), result)
|
||||||
# Now we call it
|
# Now we call it
|
||||||
self.generateCall(result, argExpr, node.token.line)
|
self.generateCall(result, argExpr, node.token.line)
|
||||||
of NodeKind.callExpr:
|
of NodeKind.callExpr:
|
||||||
|
@ -1849,6 +1911,44 @@ proc importStmt(self: Compiler, node: ImportStmt) =
|
||||||
self.error(&"""could not import '{filename}': {getCurrentExceptionMsg()} [errno {osLastError()}]""")
|
self.error(&"""could not import '{filename}': {getCurrentExceptionMsg()} [errno {osLastError()}]""")
|
||||||
|
|
||||||
|
|
||||||
|
proc printRepl(self: Compiler, typ: Type, node: Expression) =
|
||||||
|
## Emits instruction to print
|
||||||
|
## peon types in REPL mode
|
||||||
|
case typ.kind:
|
||||||
|
of Generic:
|
||||||
|
discard # TODO
|
||||||
|
of Int64:
|
||||||
|
self.emitByte(PrintInt64, node.token.line)
|
||||||
|
of UInt64:
|
||||||
|
self.emitByte(PrintUInt64, node.token.line)
|
||||||
|
of Int32:
|
||||||
|
self.emitByte(PrintInt32, node.token.line)
|
||||||
|
of UInt32:
|
||||||
|
self.emitByte(PrintInt32, node.token.line)
|
||||||
|
of Int16:
|
||||||
|
self.emitByte(PrintInt16, node.token.line)
|
||||||
|
of UInt16:
|
||||||
|
self.emitByte(PrintUInt16, node.token.line)
|
||||||
|
of Int8:
|
||||||
|
self.emitByte(PrintInt8, node.token.line)
|
||||||
|
of UInt8:
|
||||||
|
self.emitByte(PrintUInt8, node.token.line)
|
||||||
|
of Float64:
|
||||||
|
self.emitByte(PrintFloat64, node.token.line)
|
||||||
|
of Float32:
|
||||||
|
self.emitByte(PrintFloat32, node.token.line)
|
||||||
|
of Bool:
|
||||||
|
self.emitByte(PrintBool, node.token.line)
|
||||||
|
of Nan:
|
||||||
|
self.emitByte(PrintNan, node.token.line)
|
||||||
|
of Inf:
|
||||||
|
self.emitByte(PrintInf, node.token.line)
|
||||||
|
of String:
|
||||||
|
self.emitByte(PrintString, node.token.line)
|
||||||
|
else:
|
||||||
|
self.emitByte(PrintHex, node.token.line)
|
||||||
|
|
||||||
|
|
||||||
proc statement(self: Compiler, node: Statement) =
|
proc statement(self: Compiler, node: Statement) =
|
||||||
## Compiles all statements
|
## Compiles all statements
|
||||||
case node.kind:
|
case node.kind:
|
||||||
|
@ -1861,37 +1961,7 @@ proc statement(self: Compiler, node: Statement) =
|
||||||
# so we don't have to pop anything
|
# so we don't have to pop anything
|
||||||
discard
|
discard
|
||||||
elif self.replMode:
|
elif self.replMode:
|
||||||
case kind.kind:
|
self.printRepl(kind, expression)
|
||||||
of Int64:
|
|
||||||
self.emitByte(PrintInt64, node.token.line)
|
|
||||||
of UInt64:
|
|
||||||
self.emitByte(PrintUInt64, node.token.line)
|
|
||||||
of Int32:
|
|
||||||
self.emitByte(PrintInt32, node.token.line)
|
|
||||||
of UInt32:
|
|
||||||
self.emitByte(PrintInt32, node.token.line)
|
|
||||||
of Int16:
|
|
||||||
self.emitByte(PrintInt16, node.token.line)
|
|
||||||
of UInt16:
|
|
||||||
self.emitByte(PrintUInt16, node.token.line)
|
|
||||||
of Int8:
|
|
||||||
self.emitByte(PrintInt8, node.token.line)
|
|
||||||
of UInt8:
|
|
||||||
self.emitByte(PrintUInt8, node.token.line)
|
|
||||||
of Float64:
|
|
||||||
self.emitByte(PrintFloat64, node.token.line)
|
|
||||||
of Float32:
|
|
||||||
self.emitByte(PrintFloat32, node.token.line)
|
|
||||||
of Bool:
|
|
||||||
self.emitByte(PrintBool, node.token.line)
|
|
||||||
of Nan:
|
|
||||||
self.emitByte(PrintNan, node.token.line)
|
|
||||||
of Inf:
|
|
||||||
self.emitByte(PrintInf, node.token.line)
|
|
||||||
of String:
|
|
||||||
self.emitByte(PrintString, node.token.line)
|
|
||||||
else:
|
|
||||||
self.emitByte(PrintHex, node.token.line)
|
|
||||||
else:
|
else:
|
||||||
self.emitByte(Pop, node.token.line)
|
self.emitByte(Pop, node.token.line)
|
||||||
of NodeKind.ifStmt:
|
of NodeKind.ifStmt:
|
||||||
|
@ -1942,13 +2012,20 @@ proc varDecl(self: Compiler, node: VarDecl, name: Name) =
|
||||||
var name = node.value.token.lexeme
|
var name = node.value.token.lexeme
|
||||||
if node.value.kind == callExpr:
|
if node.value.kind == callExpr:
|
||||||
name = CallExpr(node.value).callee.token.lexeme
|
name = CallExpr(node.value).callee.token.lexeme
|
||||||
self.error(&"reference to undeclared name '{name}'")
|
if self.resolve(name).isNil():
|
||||||
|
self.error(&"reference to undeclared name '{name}'")
|
||||||
self.error(&"'{node.name.token.lexeme}' has no type")
|
self.error(&"'{node.name.token.lexeme}' has no type")
|
||||||
elif not expected.isNil() and expected.mutable: # I mean, variables *are* already mutable (some of them anyway)
|
elif not expected.isNil() and expected.mutable: # I mean, variables *are* already mutable (some of them anyway)
|
||||||
self.error(&"invalid type '{self.typeToStr(expected)}' for var")
|
self.error(&"invalid type '{self.typeToStr(expected)}' for var")
|
||||||
elif not self.compare(expected, actual):
|
elif not self.compare(expected, actual):
|
||||||
if not expected.isNil():
|
if not expected.isNil():
|
||||||
self.error(&"expected value of type '{self.typeToStr(expected)}', but '{node.name.token.lexeme}' is of type '{self.typeToStr(actual)}'")
|
self.error(&"expected value of type '{self.typeToStr(expected)}', but '{node.name.token.lexeme}' is of type '{self.typeToStr(actual)}'")
|
||||||
|
if expected.isNil():
|
||||||
|
name.valueType = actual
|
||||||
|
if actual.kind == Generic:
|
||||||
|
# We matched a generic type, but we
|
||||||
|
# need the concrete one
|
||||||
|
name.valueType = expected
|
||||||
self.expression(node.value)
|
self.expression(node.value)
|
||||||
self.emitByte(StoreVar, node.token.line)
|
self.emitByte(StoreVar, node.token.line)
|
||||||
self.emitBytes(self.getStackPos(self.names[^1]).toTriple(), node.token.line)
|
self.emitBytes(self.getStackPos(self.names[^1]).toTriple(), node.token.line)
|
||||||
|
|
|
@ -6,6 +6,6 @@ fn sum[T: int | int32](a, b: T): T {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# print(sum(1, 2));
|
print(sum(1, 2));
|
||||||
# print(sum(1'i32, 2'i32));
|
print(sum(1'i32, 2'i32));
|
||||||
print(sum(1'i16, 2'i16)); # Will not work if uncommented!
|
# print(sum(1'i16, 2'i16)); # Will not work if uncommented!
|
||||||
|
|
452
tests/std.pn
452
tests/std.pn
|
@ -8,94 +8,22 @@
|
||||||
# - It makes the implementation easier and more flexible
|
# - It makes the implementation easier and more flexible
|
||||||
|
|
||||||
|
|
||||||
# TODO: Use generics
|
operator `+`*[T: int | uint64 | int32 | uint32 | int16 | uint16 | int8 | uint8](a, b: T): T {
|
||||||
|
|
||||||
operator `+`*(a, b: int): int {
|
|
||||||
#pragma[magic: "Add", pure]
|
#pragma[magic: "Add", pure]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
operator `+`*(a, b: uint64): uint64 {
|
operator `+`(a, b: float): float {
|
||||||
#pragma[magic: "Add", pure]
|
#pragma[magic: "AddFloat64", pure]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
operator `+`*(a, b: int32): int32 {
|
operator `+`(a, b: float32): float32 {
|
||||||
#pragma[magic: "Add", pure]
|
#pragma[magic: "AddFloat32", pure]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
operator `+`*(a, b: uint32): uint32 {
|
operator `-`*[T: int | uint64 | int32 | uint32 | int16 | uint16 | int8 | uint8](a, b: T): T {
|
||||||
#pragma[magic: "Add", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `+`*(a, b: int16): int16 {
|
|
||||||
#pragma[magic: "Add", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `+`*(a, b: uint16): uint16 {
|
|
||||||
#pragma[magic: "Add", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `+`*(a, b: int8): int8 {
|
|
||||||
#pragma[magic: "Add", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `+`*(a, b: uint8): uint8 {
|
|
||||||
#pragma[magic: "Add", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `+`*(a, b: float64): float64 {
|
|
||||||
#pragma[magic: "Add", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `+`*(a, b: float32): float32 {
|
|
||||||
#pragma[magic: "Add", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `-`*(a, b: int): int {
|
|
||||||
#pragma[magic: "Subtract", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `-`*(a, b: uint64): uint64 {
|
|
||||||
#pragma[magic: "Subtract", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `-`*(a, b: int32): int32 {
|
|
||||||
#pragma[magic: "Subtract", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `-`*(a, b: uint32): uint32 {
|
|
||||||
#pragma[magic: "Subtract", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `-`*(a, b: int16): int16 {
|
|
||||||
#pragma[magic: "Subtract", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `-`*(a, b: uint16): uint16 {
|
|
||||||
#pragma[magic: "Subtract", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `-`*(a, b: int8): int8 {
|
|
||||||
#pragma[magic: "Subtract", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `-`*(a, b: uint8): uint8 {
|
|
||||||
#pragma[magic: "Subtract", pure]
|
#pragma[magic: "Subtract", pure]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,42 +38,7 @@ operator `-`*(a, b: float32): float32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
operator `*`*(a, b: int): int {
|
operator `*`*[T: int | uint64 | int32 | uint32 | int16 | uint16 | int8 | uint8](a, b: T): T {
|
||||||
#pragma[magic: "Multiply", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `*`*(a, b: uint64): uint64 {
|
|
||||||
#pragma[magic: "Multiply", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `*`*(a, b: int32): int32 {
|
|
||||||
#pragma[magic: "Multiply", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `*`*(a, b: uint32): uint32 {
|
|
||||||
#pragma[magic: "Multiply", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `*`*(a, b: int16): int16 {
|
|
||||||
#pragma[magic: "Multiply", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `*`*(a, b: uint16): uint16 {
|
|
||||||
#pragma[magic: "Multiply", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `*`*(a, b: int8): int8 {
|
|
||||||
#pragma[magic: "Multiply", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `*`*(a, b: uint8): uint8 {
|
|
||||||
#pragma[magic: "Multiply", pure]
|
#pragma[magic: "Multiply", pure]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,42 +53,12 @@ operator `*`*(a, b: float32): float32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
operator `/`*(a, b: int): int {
|
operator `/`*[T: int | int32 | int16 | int8](a, b: T): T {
|
||||||
#pragma[magic: "SignedDivide", pure]
|
#pragma[magic: "SignedDivide", pure]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
operator `/`*(a, b: uint64): uint64 {
|
operator `/`*[T: uint64 | uint32 | uint16 | uint8](a, b: T): T {
|
||||||
#pragma[magic: "Divide", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `/`*(a, b: int32): int32 {
|
|
||||||
#pragma[magic: "SignedDivide", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `/`*(a, b: uint32): uint32 {
|
|
||||||
#pragma[magic: "Divide", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `/`*(a, b: int16): int16 {
|
|
||||||
#pragma[magic: "SignedDivide", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `/`*(a, b: uint16): uint16 {
|
|
||||||
#pragma[magic: "Divide", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `/`*(a, b: int8): int8 {
|
|
||||||
#pragma[magic: "SignedDivide", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `/`*(a, b: uint8): uint8 {
|
|
||||||
#pragma[magic: "Divide", pure]
|
#pragma[magic: "Divide", pure]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,12 +73,12 @@ operator `/`*(a, b: float32): float32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
operator `**`*(a, b: int64): int64 {
|
operator `**`*[T: int | int32 | int16 | int8](a, b: T): T {
|
||||||
#pragma[magic: "SignedPow", pure]
|
#pragma[magic: "SignedPow", pure]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
operator `**`*(a, b: uint64): uint64 {
|
operator `**`*[T: uint64 | uint32 | uint16 | uint8](a, b: T): T {
|
||||||
#pragma[magic: "Pow", pure]
|
#pragma[magic: "Pow", pure]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,301 +89,32 @@ operator `%`*(a, b: int64): int64 {
|
||||||
|
|
||||||
# Comparison operators
|
# Comparison operators
|
||||||
|
|
||||||
operator `>`*(a, b: int): bool {
|
operator `>`*[T: int | uint64 | int32 | uint32 | int16 | uint16 | int8 | uint8 | float | float32](a, b: T): bool {
|
||||||
#pragma[magic: "GreaterThan", pure]
|
#pragma[magic: "GreaterThan", pure]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
operator `<`*(a, b: int): bool {
|
operator `<`*[T: int | uint64 | int32 | uint32 | int16 | uint16 | int8 | uint8 | float | float32](a, b: T): bool {
|
||||||
#pragma[magic: "LessThan", pure]
|
#pragma[magic: "LessThan", pure]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
operator `==`*(a, b: int): bool {
|
operator `==`*[T: int | uint64 | int32 | uint32 | int16 | uint16 | int8 | uint8 | float | float32](a, b: T): bool {
|
||||||
#pragma[magic: "Equal", pure]
|
#pragma[magic: "Equal", pure]
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
operator `!=`*(a, b: int): bool {
|
operator `!=`*[T: int | uint64 | int32 | uint32 | int16 | uint16 | int8 | uint8 | float | float32](a, b: T): bool {
|
||||||
#pragma[magic: "NotEqual", pure]
|
#pragma[magic: "NotEqual", pure]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
operator `>`*(a, b: uint64): bool {
|
operator `>=`*[T: int | uint64 | int32 | uint32 | int16 | uint16 | int8 | uint8 | float | float32](a, b: T): bool {
|
||||||
#pragma[magic: "GreaterThan", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `<`*(a, b: uint64): bool {
|
|
||||||
#pragma[magic: "LessThan", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `==`*(a, b: uint64): bool {
|
|
||||||
#pragma[magic: "Equal", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `!=`*(a, b: uint64): bool {
|
|
||||||
#pragma[magic: "NotEqual", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `>`*(a, b: int32): bool {
|
|
||||||
#pragma[magic: "GreaterThan", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `<`*(a, b: int32): bool {
|
|
||||||
#pragma[magic: "LessThan", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `==`*(a, b: int32): bool {
|
|
||||||
#pragma[magic: "Equal", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `!=`*(a, b: int32): bool {
|
|
||||||
#pragma[magic: "NotEqual", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
operator `>`*(a, b: uint32): bool {
|
|
||||||
#pragma[magic: "GreaterThan", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `<`*(a, b: uint32): bool {
|
|
||||||
#pragma[magic: "LessThan", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `==`*(a, b: uint32): bool {
|
|
||||||
#pragma[magic: "Equal", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `!=`*(a, b: uint32): bool {
|
|
||||||
#pragma[magic: "NotEqual", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `>`*(a, b: int16): bool {
|
|
||||||
#pragma[magic: "GreaterThan", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `<`*(a, b: int16): bool {
|
|
||||||
#pragma[magic: "LessThan", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `==`*(a, b: int16): bool {
|
|
||||||
#pragma[magic: "Equal", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `!=`*(a, b: int16): bool {
|
|
||||||
#pragma[magic: "NotEqual", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `>`*(a, b: uint16): bool {
|
|
||||||
#pragma[magic: "GreaterThan", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `<`*(a, b: uint16): bool {
|
|
||||||
#pragma[magic: "LessThan", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `==`*(a, b: uint16): bool {
|
|
||||||
#pragma[magic: "Equal", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `!=`*(a, b: uint16): bool {
|
|
||||||
#pragma[magic: "NotEqual", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `>`*(a, b: int8): bool {
|
|
||||||
#pragma[magic: "GreaterThan", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `<`*(a, b: int8): bool {
|
|
||||||
#pragma[magic: "LessThan", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `==`*(a, b: int8): bool {
|
|
||||||
#pragma[magic: "Equal", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `!=`*(a, b: int8): bool {
|
|
||||||
#pragma[magic: "NotEqual", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `>`*(a, b: uint8): bool {
|
|
||||||
#pragma[magic: "GreaterThan", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `<`*(a, b: uint8): bool {
|
|
||||||
#pragma[magic: "LessThan", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `==`*(a, b: uint8): bool {
|
|
||||||
#pragma[magic: "Equal", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `!=`*(a, b: uint8): bool {
|
|
||||||
#pragma[magic: "NotEqual", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `>`*(a, b: float): bool {
|
|
||||||
#pragma[magic: "GreaterThan", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `<`*(a, b: float): bool {
|
|
||||||
#pragma[magic: "LessThan", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `==`*(a, b: float): bool {
|
|
||||||
#pragma[magic: "Equal", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `!=`*(a, b: float): bool {
|
|
||||||
#pragma[magic: "NotEqual", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `>`*(a, b: float32): bool {
|
|
||||||
#pragma[magic: "GreaterThan", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `<`*(a, b: float32): bool {
|
|
||||||
#pragma[magic: "LessThan", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `==`*(a, b: float32): bool {
|
|
||||||
#pragma[magic: "Equal", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `!=`*(a, b: float32): bool {
|
|
||||||
#pragma[magic: "NotEqual", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `>=`*(a, b: int): bool {
|
|
||||||
#pragma[magic: "GreaterOrEqual", pure]
|
#pragma[magic: "GreaterOrEqual", pure]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
operator `<=`*(a, b: int): bool {
|
operator `<=`*[T: int | uint64 | int32 | uint32 | int16 | uint16 | int8 | uint8 | float | float32](a, b: T): bool {
|
||||||
#pragma[magic: "LessOrEqual", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `>=`*(a, b: uint64): bool {
|
|
||||||
#pragma[magic: "GreaterOrEqual", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `<=`*(a, b: uint64): bool {
|
|
||||||
#pragma[magic: "LessOrEqual", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `>=`*(a, b: int32): bool {
|
|
||||||
#pragma[magic: "GreaterOrEqual", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `<=`*(a, b: int32): bool {
|
|
||||||
#pragma[magic: "LessOrEqual", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `>=`*(a, b: uint32): bool {
|
|
||||||
#pragma[magic: "GreaterOrEqual", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `<=`*(a, b: uint32): bool {
|
|
||||||
#pragma[magic: "LessOrEqual", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `>=`*(a, b: int16): bool {
|
|
||||||
#pragma[magic: "GreaterOrEqual", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `<=`*(a, b: int16): bool {
|
|
||||||
#pragma[magic: "LessOrEqual", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `>=`*(a, b: uint16): bool {
|
|
||||||
#pragma[magic: "GreaterOrEqual", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `<=`*(a, b: uint16): bool {
|
|
||||||
#pragma[magic: "LessOrEqual", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `>=`*(a, b: int8): bool {
|
|
||||||
#pragma[magic: "GreaterOrEqual", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `<=`*(a, b: int8): bool {
|
|
||||||
#pragma[magic: "LessOrEqual", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `>=`*(a, b: uint8): bool {
|
|
||||||
#pragma[magic: "GreaterOrEqual", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `<=`*(a, b: uint8): bool {
|
|
||||||
#pragma[magic: "LessOrEqual", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `>=`*(a, b: float): bool {
|
|
||||||
#pragma[magic: "GreaterOrEqual", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `<=`*(a, b: float): bool {
|
|
||||||
#pragma[magic: "LessOrEqual", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `>=`*(a, b: float32): bool {
|
|
||||||
#pragma[magic: "GreaterOrEqual", pure]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator `<=`*(a, b: float32): bool {
|
|
||||||
#pragma[magic: "LessOrEqual", pure]
|
#pragma[magic: "LessOrEqual", pure]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -545,34 +139,34 @@ operator `&`*(a, b: int): bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
operator `|`*(a, b: int): int {
|
operator `|`*[T: int | uint64 | int32 | uint32 | int16 | uint16 | int8 | uint8](a, b: T): int {
|
||||||
#pragma[magic: "Or", pure]
|
#pragma[magic: "Or", pure]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
operator `~`*(a: int): int {
|
operator `~`*[T: int | uint64 | int32 | uint32 | int16 | uint16 | int8 | uint8](a: T): T {
|
||||||
#pragma[magic: "Not", pure]
|
#pragma[magic: "Not", pure]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
operator `>>`*(a, b: int): int {
|
operator `>>`*[T: int | uint64 | int32 | uint32 | int16 | uint16 | int8 | uint8](a, b: T): T {
|
||||||
#pragma[magic: "RShift", pure]
|
#pragma[magic: "RShift", pure]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
operator `<<`*(a, b: int): int {
|
operator `<<`*[T: int | uint64 | int32 | uint32 | int16 | uint16 | int8 | uint8](a, b: T): T {
|
||||||
#pragma[magic: "LShift", pure]
|
#pragma[magic: "LShift", pure]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
operator `^`*(a, b: int): int {
|
operator `^`*[T: int | uint64 | int32 | uint32 | int16 | uint16 | int8 | uint8](a, b: T): T {
|
||||||
#pragma[magic: "Xor", pure]
|
#pragma[magic: "Xor", pure]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# Assignment operators
|
# Assignment operators
|
||||||
|
|
||||||
operator `=`*[T: all](a: var T, b: T) {
|
operator `=`*[T: all](a: var T, b: T) { # TODO: This is just a placeholder right now
|
||||||
#pragma[magic: "GenericAssign"]
|
#pragma[magic: "GenericAssign"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue