Initial work on call resolution, added support for running files

This commit is contained in:
Mattia Giambirtone 2022-05-22 13:02:48 +02:00
parent 6d6ae3ee7a
commit 42ab1d4c6e
10 changed files with 352 additions and 56 deletions

BIN
main Executable file

Binary file not shown.

BIN
peon Executable file

Binary file not shown.

View File

@ -23,6 +23,7 @@ import algorithm
import parseutils import parseutils
import strutils import strutils
import sequtils import sequtils
import os
export ast export ast
@ -43,9 +44,11 @@ type
node*: ASTNode node*: ASTNode
case kind*: TypeKind: case kind*: TypeKind:
of Function: of Function:
args*: seq[tuple[name: IdentExpr, kind: Type]]
returnType*: Type returnType*: Type
else: else:
discard discard
# This way we don't have recursive dependency issues # This way we don't have recursive dependency issues
import meta/bytecode import meta/bytecode
export bytecode export bytecode
@ -158,6 +161,8 @@ proc identifier(self: Compiler, node: IdentExpr)
proc varDecl(self: Compiler, node: VarDecl) proc varDecl(self: Compiler, node: VarDecl)
proc inferType(self: Compiler, node: LiteralExpr): Type proc inferType(self: Compiler, node: LiteralExpr): Type
proc inferType(self: Compiler, node: Expression): Type proc inferType(self: Compiler, node: Expression): Type
proc findByName(self: Compiler, name: string): seq[Name]
proc findByType(self: Compiler, name: string, kind: Type): seq[Name]
## End of forward declarations ## End of forward declarations
## Public getter for nicer error formatting ## Public getter for nicer error formatting
@ -190,7 +195,7 @@ proc done(self: Compiler): bool =
proc error(self: Compiler, message: string) {.raises: [CompileError].} = proc error(self: Compiler, message: string) {.raises: [CompileError].} =
## Raises a CompileError exception ## Raises a CompileError exception
raise newException(CompileError, message) raise CompileError(msg: message, node: self.getCurrentNode(), file: self.file, module: self.currentModule)
proc step(self: Compiler): ASTNode = proc step(self: Compiler): ASTNode =
@ -201,7 +206,7 @@ proc step(self: Compiler): ASTNode =
self.current += 1 self.current += 1
proc emitByte(self: Compiler, byt: OpCode|uint8) = proc emitByte(self: Compiler, byt: OpCode | uint8) =
## Emits a single byte, writing it to ## Emits a single byte, writing it to
## the current chunk being compiled ## the current chunk being compiled
when DEBUG_TRACE_COMPILER: when DEBUG_TRACE_COMPILER:
@ -209,23 +214,8 @@ proc emitByte(self: Compiler, byt: OpCode|uint8) =
self.chunk.write(uint8 byt, self.peek().token.line) self.chunk.write(uint8 byt, self.peek().token.line)
proc emitBytes(self: Compiler, byt1: OpCode|uint8, byt2: OpCode|uint8) = proc emitBytes(self: Compiler, bytarr: openarray[OpCode | uint8]) =
## Emits multiple bytes instead of a single one. This is useful ## Handy helper method to write arbitrary bytes into
## to emit operators along with their operands or for multi-byte
## instructions that are longer than one byte
self.emitByte(uint8 byt1)
self.emitByte(uint8 byt2)
proc emitBytes(self: Compiler, bytarr: array[2, uint8]) =
## Handy helper method to write an array of 2 bytes into
## the current chunk, calling emitByte on each of its
## elements
self.emitBytes(bytarr[0], bytarr[1])
proc emitBytes(self: Compiler, bytarr: openarray[uint8]) =
## Handy helper method to write an array of 3 bytes into
## the current chunk, calling emitByte on each of its ## the current chunk, calling emitByte on each of its
## elements ## elements
for b in bytarr: for b in bytarr:
@ -390,6 +380,30 @@ proc detectClosureVariable(self: Compiler, name: IdentExpr,
self.chunk.code[entry.codePos + 2] = idx[1] self.chunk.code[entry.codePos + 2] = idx[1]
self.chunk.code[entry.codePos + 3] = idx[2] self.chunk.code[entry.codePos + 3] = idx[2]
proc compareTypes(self: Compiler, a, b: Type): bool
proc compareTypesWithNullNode(self: Compiler, a, b: Type): bool =
## Compares two types without using information from
## AST nodes
if a == nil:
return b == nil
elif b == nil:
return a == nil
if a.kind != b.kind:
return false
case a.kind:
of Function:
if a.args.len() != b.args.len():
return false
elif not self.compareTypes(a.returnType, b.returnType):
return false
for (argA, argB) in zip(a.args, b.args):
if not self.compareTypes(argA.kind, argB.kind):
return false
return true
else:
discard
proc compareTypes(self: Compiler, a, b: Type): bool = proc compareTypes(self: Compiler, a, b: Type): bool =
## Compares two type objects ## Compares two type objects
@ -406,6 +420,8 @@ proc compareTypes(self: Compiler, a, b: Type): bool =
Char, Byte, String, Nil, Nan, Bool, Inf: Char, Byte, String, Nil, Nan, Bool, Inf:
return true return true
of Function: of Function:
if a.node == nil or b.node == nil:
return self.compareTypesWithNullNode(a, b)
let let
a = FunDecl(a.node) a = FunDecl(a.node)
b = FunDecl(b.node) b = FunDecl(b.node)
@ -413,8 +429,7 @@ proc compareTypes(self: Compiler, a, b: Type): bool =
return false return false
elif a.arguments.len() != b.arguments.len(): elif a.arguments.len() != b.arguments.len():
return false return false
elif not self.compareTypes(self.inferType(a.returnType), elif not self.compareTypes(self.inferType(a.returnType), self.inferType(b.returnType)):
self.inferType(b.returnType)):
return false return false
for (argA, argB) in zip(a.arguments, b.arguments): for (argA, argB) in zip(a.arguments, b.arguments):
if argA.mutable != argB.mutable: if argA.mutable != argB.mutable:
@ -423,8 +438,7 @@ proc compareTypes(self: Compiler, a, b: Type): bool =
return false return false
elif argA.isPtr != argB.isPtr: elif argA.isPtr != argB.isPtr:
return false return false
elif not self.compareTypes(self.inferType(argA.valueType), elif not self.compareTypes(self.inferType(argA.valueType), self.inferType(argB.valueType)):
self.inferType(argB.valueType)):
return false return false
return true return true
else: else:
@ -702,7 +716,10 @@ proc unary(self: Compiler, node: UnaryExpr) =
## Compiles unary expressions such as decimal ## Compiles unary expressions such as decimal
## and bitwise negation ## and bitwise negation
self.expression(node.a) # Pushes the operand onto the stack self.expression(node.a) # Pushes the operand onto the stack
let valueType = self.inferType(node.a)
let impl = self.findByType(node.token.lexeme, Type(kind: Function, returnType: valueType, node: nil))
if impl.len() == 0:
self.error(&"cannot find a suitable implementation for '{node.token.lexeme}'")
proc binary(self: Compiler, node: BinaryExpr) = proc binary(self: Compiler, node: BinaryExpr) =
@ -772,10 +789,12 @@ proc declareName(self: Compiler, node: Declaration) =
owner: self.currentModule, owner: self.currentModule,
valueType: Type(kind: Function, node: node, valueType: Type(kind: Function, node: node,
returnType: self.inferType( returnType: self.inferType(
node.returnType)), node.returnType),
args: @[]),
codePos: self.chunk.code.len(), codePos: self.chunk.code.len(),
name: node.name, name: node.name,
isLet: false)) isLet: false))
let fn = self.names[^1]
for argument in node.arguments: for argument in node.arguments:
if self.names.high() > 16777215: if self.names.high() > 16777215:
self.error("cannot declare more than 16777216 variables at a time") self.error("cannot declare more than 16777216 variables at a time")
@ -789,6 +808,7 @@ proc declareName(self: Compiler, node: Declaration) =
isLet: false)) isLet: false))
self.names[^1].valueType = self.inferType(argument.valueType) self.names[^1].valueType = self.inferType(argument.valueType)
self.names[^1].valueType.node = argument.name self.names[^1].valueType.node = argument.name
fn.valueType.args.add((node.name, self.names[^1].valueType))
self.emitByte(LoadVar) self.emitByte(LoadVar)
self.emitBytes(self.names.high().toTriple()) self.emitBytes(self.names.high().toTriple())
else: else:
@ -1274,7 +1294,7 @@ proc compile*(self: Compiler, ast: seq[Declaration], file: string): Chunk =
self.names = @[] self.names = @[]
self.scopeDepth = 0 self.scopeDepth = 0
self.currentFunction = nil self.currentFunction = nil
self.currentModule = self.file self.currentModule = self.file.extractFilename()
self.current = 0 self.current = 0
while not self.done(): while not self.done():
self.declaration(Declaration(self.step())) self.declaration(Declaration(self.step()))

View File

@ -19,7 +19,6 @@ import strutils
import parseutils import parseutils
import strformat import strformat
import tables import tables
import terminal
import meta/token import meta/token
@ -203,7 +202,7 @@ proc step(self: Lexer, n: int = 1): string =
inc(self.current) inc(self.current)
proc peek*(self: Lexer, distance: int = 0, length: int = 1): string = proc peek(self: Lexer, distance: int = 0, length: int = 1): string =
## Returns a stream of characters of ## Returns a stream of characters of
## at most length bytes from the source ## at most length bytes from the source
## file, starting at the given distance, ## file, starting at the given distance,
@ -226,7 +225,7 @@ proc peek*(self: Lexer, distance: int = 0, length: int = 1): string =
proc error(self: Lexer, message: string) = proc error(self: Lexer, message: string) =
## Raises a lexing error with a formatted ## Raises a lexing error with a formatted
## error message ## error message
raise newException(LexingError, message) raise LexingError(msg: message, line: self.line, file: self.file, lexeme: self.peek())
proc check(self: Lexer, s: string, distance: int = 0): bool = proc check(self: Lexer, s: string, distance: int = 0): bool =

View File

@ -11,12 +11,24 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import token
import ast
type type
## Nim exceptions for internal Peon failures ## Nim exceptions for internal Peon failures
PeonException* = object of CatchableError PeonException* = ref object of CatchableError
LexingError* = object of PeonException LexingError* = ref object of PeonException
ParseError* = object of PeonException file*: string
CompileError* = object of PeonException lexeme*: string
SerializationError* = object of PeonException line*: int
ParseError* = ref object of PeonException
file*: string
token*: Token
module*: string
CompileError* = ref object of PeonException
node*: ASTNode
file*: string
module*: string
SerializationError* = ref object of PeonException
file*: string

View File

@ -17,6 +17,7 @@
import strformat import strformat
import strutils import strutils
import tables import tables
import os
import meta/token import meta/token
import meta/ast import meta/ast
@ -152,6 +153,7 @@ proc getCurrentToken*(self: Parser): Token {.inline.} = (if self.getCurrent() >=
self.getCurrent() - 1 < 0: self.tokens[^1] else: self.tokens[self.current - 1]) self.getCurrent() - 1 < 0: self.tokens[^1] else: self.tokens[self.current - 1])
proc getCurrentFunction*(self: Parser): Declaration {.inline.} = self.currentFunction proc getCurrentFunction*(self: Parser): Declaration {.inline.} = self.currentFunction
proc getFile*(self: Parser): string {.inline.} = self.file proc getFile*(self: Parser): string {.inline.} = self.file
proc getModule*(self: Parser): string {.inline.} = self.getFile().extractFilename()
# Handy templates to make our life easier, thanks nim! # Handy templates to make our life easier, thanks nim!
template endOfFile: Token = Token(kind: EndOfFile, lexeme: "", line: -1) template endOfFile: Token = Token(kind: EndOfFile, lexeme: "", line: -1)
@ -192,7 +194,7 @@ proc step(self: Parser, n: int = 1): Token =
proc error(self: Parser, message: string) {.raises: [ParseError].} = proc error(self: Parser, message: string) {.raises: [ParseError].} =
## Raises a ParseError exception ## Raises a ParseError exception
raise newException(ParseError, message) raise ParseError(msg: message, token: self.getCurrentToken(), file: self.file, module: self.getModule())
# Why do we allow strings or enum members of TokenType? Well, it's simple: # Why do we allow strings or enum members of TokenType? Well, it's simple:

View File

@ -2,6 +2,7 @@
import strformat import strformat
import strutils import strutils
import terminal import terminal
import os
# Thanks art <3 # Thanks art <3
import jale/editor as ed import jale/editor as ed
import jale/templates import jale/templates
@ -18,7 +19,6 @@ import frontend/compiler as c
import backend/vm as v import backend/vm as v
import util/serializer as s import util/serializer as s
# Forward declarations # Forward declarations
proc fillSymbolTable(tokenizer: Lexer) proc fillSymbolTable(tokenizer: Lexer)
proc getLineEditor: LineEditor proc getLineEditor: LineEditor
@ -38,8 +38,8 @@ when debugCompiler:
import util/debugger import util/debugger
when isMainModule: proc repl =
setControlCHook(proc () {.noconv.} = quit(0)) styledEcho fgMagenta, "Welcome into the peon REPL!"
var var
keep = true keep = true
tokens: seq[Token] = @[] tokens: seq[Token] = @[]
@ -121,50 +121,116 @@ when isMainModule:
when debugRuntime: when debugRuntime:
styledEcho fgCyan, "\n\nExecution step: " styledEcho fgCyan, "\n\nExecution step: "
vm.run(serialized.chunk) vm.run(serialized.chunk)
# TODO: The code for error reporting completely
# breaks down with multiline input, fix it
except LexingError: except LexingError:
let lineNo = tokenizer.getLine() let exc = LexingError(getCurrentException())
let relPos = tokenizer.getRelPos(lineNo) let relPos = tokenizer.getRelPos(exc.line)
let line = tokenizer.getSource().splitLines()[lineNo - 1].strip() let line = tokenizer.getSource().splitLines()[exc.line - 1].strip()
stderr.styledWriteLine(fgRed, "A fatal error occurred while parsing ", fgYellow, &"'{tokenizer.getFile()}'", fgRed, ", module ", stderr.styledWriteLine(fgRed, "A fatal error occurred while parsing ", fgYellow, &"'{exc.file}'", fgRed, ", module ",
fgYellow, &"'{tokenizer.getFile()}'", fgRed, ", line ", fgYellow, $lineNo, fgRed, " at ", fgYellow, &"'{tokenizer.peek()}'", fgYellow, &"'{exc.file.extractFilename()}'", fgRed, ", line ", fgYellow, $exc.line, fgRed, " at ", fgYellow, &"'{exc.lexeme}'",
fgRed, ": ", fgGreen , getCurrentExceptionMsg()) fgRed, ": ", fgGreen , getCurrentExceptionMsg())
styledEcho fgBlue, "Source line: " , fgDefault, line styledEcho fgBlue, "Source line: " , fgDefault, line
styledEcho fgCyan, " ".repeat(len("Source line: ")) & "^".repeat(relPos.stop - relPos.start) styledEcho fgCyan, " ".repeat(len("Source line: ")) & "^".repeat(relPos.stop - relPos.start)
except ParseError: except ParseError:
let lexeme = parser.getCurrentToken().lexeme let exc = ParseError(getCurrentException())
let lineNo = parser.getCurrentToken().line let lexeme = exc.token.lexeme
let lineNo = exc.token.line
let relPos = tokenizer.getRelPos(lineNo) let relPos = tokenizer.getRelPos(lineNo)
let fn = parser.getCurrentFunction() let fn = parser.getCurrentFunction()
let line = tokenizer.getSource().splitLines()[lineNo - 1].strip() let line = tokenizer.getSource().splitLines()[lineNo - 1].strip()
var fnMsg = "" var fnMsg = ""
if fn != nil and fn.kind == funDecl: if fn != nil and fn.kind == funDecl:
fnMsg &= &"in function '{FunDecl(fn).name.token.lexeme}'" fnMsg &= &"in function '{FunDecl(fn).name.token.lexeme}'"
stderr.styledWriteLine(fgRed, "A fatal error occurred while parsing ", fgYellow, &"'{parser.getFile()}'", fgRed, ", module ", stderr.styledWriteLine(fgRed, "A fatal error occurred while parsing ", fgYellow, &"'{exc.file}'", fgRed, ", module ",
fgYellow, &"'{parser.getFile()}'", fgRed, ", line ", fgYellow, $lineNo, fgRed, " at ", fgYellow, &"'{lexeme}'", fgYellow, &"'{exc.file}'", fgRed, ", line ", fgYellow, $lineNo, fgRed, " at ", fgYellow, &"'{lexeme}'",
fgRed, ": ", fgGreen , getCurrentExceptionMsg()) fgRed, ": ", fgGreen , getCurrentExceptionMsg())
styledEcho fgBlue, "Source line: " , fgDefault, line styledEcho fgBlue, "Source line: " , fgDefault, line
styledEcho fgCyan, " ".repeat(len("Source line: ")) & "^".repeat(relPos.stop - relPos.start) styledEcho fgCyan, " ".repeat(len("Source line: ")) & "^".repeat(relPos.stop - relPos.start)
except CompileError: except CompileError:
let lexeme = compiler.getCurrentNode().token.lexeme let exc = CompileError(getCurrentException())
let lineNo = compiler.getCurrentNode().token.line let lexeme = exc.node.token.lexeme
let lineNo = exc.node.token.line
let relPos = tokenizer.getRelPos(lineNo) let relPos = tokenizer.getRelPos(lineNo)
let line = tokenizer.getSource().splitLines()[lineNo - 1].strip() let line = tokenizer.getSource().splitLines()[lineNo - 1].strip()
var fn = compiler.getCurrentFunction() var fn = compiler.getCurrentFunction()
var fnMsg = "" var fnMsg = ""
if fn != nil and fn.kind == funDecl: if fn != nil and fn.kind == funDecl:
fnMsg &= &"in function '{FunDecl(fn).name.token.lexeme}'" fnMsg &= &"in function '{FunDecl(fn).name.token.lexeme}'"
stderr.styledWriteLine(fgRed, "A fatal error occurred while compiling ", fgYellow, &"'{compiler.getFile()}'", fgRed, ", module ", stderr.styledWriteLine(fgRed, "A fatal error occurred while compiling ", fgYellow, &"'{exc.file}'", fgRed, ", module ",
fgYellow, &"'{compiler.getModule()}'", fgRed, ", line ", fgYellow, $lineNo, fgRed, " at ", fgYellow, &"'{lexeme}'", fgYellow, &"'{exc.module}'", fgRed, ", line ", fgYellow, $lineNo, fgRed, " at ", fgYellow, &"'{lexeme}'",
fgRed, ": ", fgGreen , getCurrentExceptionMsg()) fgRed, ": ", fgGreen , getCurrentExceptionMsg())
styledEcho fgBlue, "Source line: " , fgDefault, line styledEcho fgBlue, "Source line: " , fgDefault, line
styledEcho fgCyan, " ".repeat(len("Source line: ")) & "^".repeat(relPos.stop - relPos.start) styledEcho fgCyan, " ".repeat(len("Source line: ")) & "^".repeat(relPos.stop - relPos.start)
except SerializationError: except SerializationError:
stderr.styledWriteLine(fgRed, getCurrentExceptionMsg()) let exc = SerializationError(getCurrentException())
stderr.styledWriteLine(fgRed, "A fatal error occurred while (de-)serializing", fgYellow, &"'{exc.file}'", fgGreen, ": ", getCurrentExceptionMsg())
quit(0) quit(0)
proc runFile(f: string) =
var
tokenizer = newLexer()
parser = newParser()
compiler = newCompiler()
vm = newPeonVM()
tokenizer.fillSymbolTable()
try:
vm.run(compiler.compile(parser.parse(tokenizer.lex(readFile(f), f), f), f))
except LexingError:
let exc = LexingError(getCurrentException())
let relPos = tokenizer.getRelPos(exc.line)
let line = tokenizer.getSource().splitLines()[exc.line - 1].strip()
stderr.styledWriteLine(fgRed, "A fatal error occurred while parsing ", fgYellow, &"'{exc.file}'", fgRed, ", module ",
fgYellow, &"'{exc.file}'", fgRed, ", line ", fgYellow, $exc.line, fgRed, " at ", fgYellow, &"'{exc.lexeme}'",
fgRed, ": ", fgGreen , getCurrentExceptionMsg())
styledEcho fgBlue, "Source line: " , fgDefault, line
styledEcho fgCyan, " ".repeat(len("Source line: ")) & "^".repeat(relPos.stop - relPos.start)
except ParseError:
let exc = ParseError(getCurrentException())
let lexeme = exc.token.lexeme
let lineNo = exc.token.line
let relPos = tokenizer.getRelPos(lineNo)
let fn = parser.getCurrentFunction()
let line = tokenizer.getSource().splitLines()[lineNo - 1].strip()
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())
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()
var fn = 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())
styledEcho fgBlue, "Source line: " , fgDefault, line
styledEcho fgCyan, " ".repeat(len("Source line: ")) & "^".repeat(relPos.stop - relPos.start)
except SerializationError:
let exc = SerializationError(getCurrentException())
stderr.styledWriteLine(fgRed, "A fatal error occurred while (de-)serializing", fgYellow, &"'{exc.file}'", fgGreen, ": ", getCurrentExceptionMsg())
except IOError:
stderr.styledWriteLine("An error occurred while trying to read ", fgYellow, &"'{f}'", fgRed, &": {getCurrentExceptionMsg()}")
except OSError:
stderr.styledWriteLine("An error occurred while trying to read ", fgYellow, &"'{f}'", fgRed, &": {osErrorMsg(osLastError())} [errno {osLastError()}]")
when isMainModule:
setControlCHook(proc () {.noconv.} = quit(0))
let args = commandLineParams()
if args.len() == 0:
repl()
else:
runFile(args[0])
proc fillSymbolTable(tokenizer: Lexer) = proc fillSymbolTable(tokenizer: Lexer) =
## Initializes the Lexer's symbol ## Initializes the Lexer's symbol

View File

@ -0,0 +1,193 @@
## Builtin arithmetic operators for Peon
operator `+`(a, b: int): int {
#pragma[magic: AddInt64, pure]
return;
}
operator `+`(a, b: uint): uint {
#pragma[magic: AddUInt64, pure]
return;
}
operator `+`(a, b: int32): int32 {
#pragma[magic: AddInt32, pure]
return;
}
operator `+`(a, b: uint32): uint32 {
#pragma[magic: AddUInt32, pure]
return;
}
operator `+`(a, b: int16): int16 {
#pragma[magic: AddInt16, pure]
return;
}
operator `+`(a, b: uint16): uint16 {
#pragma[magic: AddUInt16, pure]
return;
}
operator `+`(a, b: int8): int8 {
#pragma[magic: AddInt8, pure]
return;
}
operator `+`(a, b: uint8): uint8 {
#pragma[magic: AddUInt8, pure]
return;
}
operator `-`(a, b: int): int {
#pragma[magic: SubInt64, pure]
return;
}
operator `-`(a, b: uint): uint {
#pragma[magic: SubUInt64, pure]
return;
}
operator `-`(a, b: int32): int32 {
#pragma[magic: SubInt32, pure]
return;
}
operator `-`(a, b: uint32): uint32 {
#pragma[magic: SubUInt32, pure]
return;
}
operator `-`(a, b: int16): int16 {
#pragma[magic: SubInt16, pure]
return;
}
operator `-`(a, b: uint16): uint16 {
#pragma[magic: SubUInt16, pure]
return;
}
operator `-`(a, b: int8): int8 {
#pragma[magic: SubInt8, pure]
return;
}
operator `-`(a, b: uint8): uint8 {
#pragma[magic: SubUInt8, pure]
return;
}
operator `*`(a, b: int): int {
#pragma[magic: MulInt64, pure]
return;
}
operator `*`(a, b: uint): uint {
#pragma[magic: MulUInt64, pure]
return;
}
operator `*`(a, b: int32): int32 {
#pragma[magic: MulInt32, pure]
return;
}
operator `*`(a, b: uint32): uint32 {
#pragma[magic: MulUInt32, pure]
return;
}
operator `*`(a, b: int16): int16 {
#pragma[magic: MulInt16, pure]
return;
}
operator `*`(a, b: uint16): uint16 {
#pragma[magic: MulUInt16, pure]
return;
}
operator `*`(a, b: int8): int8 {
#pragma[magic: MulInt8, pure]
return;
}
operator `*`(a, b: uint8): uint8 {
#pragma[magic: MulUInt8, pure]
return;
}
operator `/`(a, b: int): int {
#pragma[magic: DivInt64, pure]
return;
}
operator `/`(a, b: uint): uint {
#pragma[magic: DivUInt64, pure]
return;
}
operator `/`(a, b: int32): int32 {
#pragma[magic: DivInt32, pure]
return;
}
operator `/`(a, b: uint32): uint32 {
#pragma[magic: DivUInt32, pure]
return;
}
operator `/`(a, b: int16): int16 {
#pragma[magic: DivInt16, pure]
return;
}
operator `/`(a, b: uint16): uint16 {
#pragma[magic: DivUInt16, pure]
return;
}
operator `/`(a, b: int8): int8 {
#pragma[magic: DivInt8, pure]
return;
}
operator `/`(a, b: uint8): uint8 {
#pragma[magic: DivUInt8, pure]
return;
}

5
src/tests.pn Normal file
View File

@ -0,0 +1,5 @@
operator `+`(a: int): int {
return a;
}
+1;

View File

@ -49,8 +49,7 @@ proc `$`*(self: Serialized): string =
proc error(self: Serializer, message: string) = proc error(self: Serializer, message: string) =
## Raises a formatted SerializationError exception ## Raises a formatted SerializationError exception
raise newException(SerializationError, raise SerializationError(msg: message, file: self.filename)
&"A fatal error occurred while (de)serializing '{self.filename}' -> {message}")
proc newSerializer*(self: Serializer = nil): Serializer = proc newSerializer*(self: Serializer = nil): Serializer =