Added built-in operators as a single instruction (src/peon/stdlib/arithmetics.pn is now fully functional)
This commit is contained in:
parent
73381513f9
commit
4591e5ca0e
|
@ -500,6 +500,107 @@ proc dispatch*(self: PeonVM) =
|
|||
self.ip += self.readLong()
|
||||
else:
|
||||
discard self.pop()
|
||||
# Built-in operations on primitive types
|
||||
of AddInt64:
|
||||
self.push(PeonObject(kind: Int64, long: self.pop().long + self.pop().long))
|
||||
of SubInt64:
|
||||
let second = self.pop()
|
||||
self.push(PeonObject(kind: Int64, long: self.pop().long - second.long))
|
||||
of MulInt64:
|
||||
self.push(PeonObject(kind: Int64, long: self.pop().long * self.pop().long))
|
||||
of DivInt64:
|
||||
let second = self.pop()
|
||||
self.push(PeonObject(kind: Int64, long: self.pop().long div second.long))
|
||||
of AddUInt64:
|
||||
self.push(PeonObject(kind: UInt64, uLong: self.pop().uLong + self.pop().uLong))
|
||||
of SubUInt64:
|
||||
let second = self.pop()
|
||||
self.push(PeonObject(kind: UInt64, uLong: self.pop().uLong - second.uLong))
|
||||
of MulUInt64:
|
||||
self.push(PeonObject(kind: UInt64, uLong: self.pop().uLong * self.pop().uLong))
|
||||
of DivUInt64:
|
||||
let second = self.pop()
|
||||
self.push(PeonObject(kind: UInt64, uLong: self.pop().uLong div second.uLong))
|
||||
of AddInt32:
|
||||
self.push(PeonObject(kind: Int32, `int`: self.pop().`int` + self.pop().`int`))
|
||||
of SubInt32:
|
||||
let second = self.pop()
|
||||
self.push(PeonObject(kind: Int32, `int`: self.pop().`int` - second.`int`))
|
||||
of MulInt32:
|
||||
self.push(PeonObject(kind: Int32, `int`: self.pop().`int` * self.pop().`int`))
|
||||
of DivInt32:
|
||||
let second = self.pop()
|
||||
self.push(PeonObject(kind: Int32, `int`: self.pop().`int` div second.`int`))
|
||||
of AddUInt32:
|
||||
self.push(PeonObject(kind: UInt32, uInt: self.pop().uInt + self.pop().uInt))
|
||||
of SubUInt32:
|
||||
let second = self.pop()
|
||||
self.push(PeonObject(kind: UInt32, uInt: self.pop().uInt - second.uInt))
|
||||
of MulUInt32:
|
||||
self.push(PeonObject(kind: UInt32, uInt: self.pop().uInt * self.pop().uInt))
|
||||
of DivUInt32:
|
||||
let second = self.pop()
|
||||
self.push(PeonObject(kind: UInt32, uInt: self.pop().uInt div second.uInt))
|
||||
of AddInt16:
|
||||
self.push(PeonObject(kind: Int16, short: self.pop().short + self.pop().short))
|
||||
of SubInt16:
|
||||
let second = self.pop()
|
||||
self.push(PeonObject(kind: Int16, short: self.pop().short - second.short))
|
||||
of MulInt16:
|
||||
self.push(PeonObject(kind: Int16, short: self.pop().short * self.pop().short))
|
||||
of DivInt16:
|
||||
let second = self.pop()
|
||||
self.push(PeonObject(kind: Int16, short: self.pop().short div second.short))
|
||||
of AddUInt16:
|
||||
self.push(PeonObject(kind: UInt16, uShort: self.pop().uShort + self.pop().uShort))
|
||||
of SubUInt16:
|
||||
let second = self.pop()
|
||||
self.push(PeonObject(kind: UInt16, uShort: self.pop().uShort - second.uShort))
|
||||
of MulUInt16:
|
||||
self.push(PeonObject(kind: UInt16, uShort: self.pop().uShort * self.pop().uShort))
|
||||
of DivUInt16:
|
||||
let second = self.pop()
|
||||
self.push(PeonObject(kind: UInt16, uShort: self.pop().uShort div second.uShort))
|
||||
of AddInt8:
|
||||
self.push(PeonObject(kind: Int8, tiny: self.pop().tiny + self.pop().tiny))
|
||||
of SubInt8:
|
||||
let second = self.pop()
|
||||
self.push(PeonObject(kind: Int8, tiny: self.pop().tiny - second.tiny))
|
||||
of MulInt8:
|
||||
self.push(PeonObject(kind: Int8, tiny: self.pop().tiny * self.pop().tiny))
|
||||
of DivInt8:
|
||||
let second = self.pop()
|
||||
self.push(PeonObject(kind: Int8, tiny: self.pop().tiny div second.tiny))
|
||||
of AddUInt8:
|
||||
self.push(PeonObject(kind: UInt8, uTiny: self.pop().uTiny + self.pop().uTiny))
|
||||
of SubUInt8:
|
||||
let second = self.pop()
|
||||
self.push(PeonObject(kind: UInt8, uTiny: self.pop().uTiny - second.uTiny))
|
||||
of MulUInt8:
|
||||
self.push(PeonObject(kind: UInt8, uTiny: self.pop().uTiny * self.pop().uTiny))
|
||||
of DivUInt8:
|
||||
let second = self.pop()
|
||||
self.push(PeonObject(kind: UInt8, uTiny: self.pop().uTiny div second.uTiny))
|
||||
of AddFloat64:
|
||||
self.push(PeonObject(kind: Float64, `float`: self.pop().`float` + self.pop().`float`))
|
||||
of SubFloat64:
|
||||
let second = self.pop()
|
||||
self.push(PeonObject(kind: Float64, `float`: self.pop().`float` - second.`float`))
|
||||
of MulFloat64:
|
||||
self.push(PeonObject(kind: Float64, `float`: self.pop().`float` * self.pop().`float`))
|
||||
of DivFloat64:
|
||||
let second = self.pop()
|
||||
self.push(PeonObject(kind: Float64, `float`: self.pop().`float` / second.`float`))
|
||||
of AddFloat32:
|
||||
self.push(PeonObject(kind: Float32, halfFloat: self.pop().halfFloat + self.pop().halfFloat))
|
||||
of SubFloat32:
|
||||
let second = self.pop()
|
||||
self.push(PeonObject(kind: Float32, halfFloat: self.pop().halfFloat - second.halfFloat))
|
||||
of MulFloat32:
|
||||
self.push(PeonObject(kind: Float32, halfFloat: self.pop().halfFloat * self.pop().halfFloat))
|
||||
of DivFloat32:
|
||||
let second = self.pop()
|
||||
self.push(PeonObject(kind: Float32, halfFloat: self.pop().halfFloat / second.halfFloat))
|
||||
else:
|
||||
discard
|
||||
|
||||
|
|
|
@ -96,6 +96,9 @@ type
|
|||
isFunctionArgument: bool
|
||||
# Where is this node declared in the file?
|
||||
line: int
|
||||
# is this a builtin function?
|
||||
isBuiltinFunction: bool
|
||||
builtinOp: string
|
||||
Loop = object
|
||||
## A "loop object" used
|
||||
## by the compiler to emit
|
||||
|
@ -183,7 +186,7 @@ proc compareTypes(self: Compiler, a, b: Type): bool
|
|||
proc patchReturnAddress(self: Compiler, pos: int)
|
||||
proc handleMagicPragma(self: Compiler, pragma: Pragma, node: ASTnode)
|
||||
proc handlePurePragma(self: Compiler, pragma: Pragma, node: ASTnode)
|
||||
|
||||
proc dispatchPragmas(self: Compiler, node: ASTnode)
|
||||
## End of forward declarations
|
||||
|
||||
|
||||
|
@ -809,9 +812,102 @@ proc emitFunction(self: Compiler, name: Name) =
|
|||
self.emitBytes(name.codePos.toTriple())
|
||||
|
||||
|
||||
proc handleBuiltinFunction(self: Compiler, fn: Name, args: seq[Expression]) =
|
||||
## Emits single instructions for builtin functions
|
||||
## such as addition or subtraction
|
||||
for argument in args:
|
||||
self.expression(argument)
|
||||
case fn.builtinOp:
|
||||
of "AddInt64":
|
||||
self.emitByte(AddInt64)
|
||||
of "SubInt64":
|
||||
self.emitByte(SubInt64)
|
||||
of "DivInt64":
|
||||
self.emitByte(DivInt64)
|
||||
of "MulInt64":
|
||||
self.emitByte(MulInt64)
|
||||
of "AddInt32":
|
||||
self.emitByte(AddInt32)
|
||||
of "SubInt32":
|
||||
self.emitByte(SubInt32)
|
||||
of "DivInt32":
|
||||
self.emitByte(DivInt32)
|
||||
of "MulInt32":
|
||||
self.emitByte(MulInt32)
|
||||
of "AddInt16":
|
||||
self.emitByte(AddInt16)
|
||||
of "SubInt16":
|
||||
self.emitByte(SubInt16)
|
||||
of "DivInt16":
|
||||
self.emitByte(DivInt16)
|
||||
of "MulInt16":
|
||||
self.emitByte(MulInt16)
|
||||
of "AddInt8":
|
||||
self.emitByte(AddInt8)
|
||||
of "SubInt8":
|
||||
self.emitByte(SubInt8)
|
||||
of "DivInt8":
|
||||
self.emitByte(DivInt8)
|
||||
of "MulInt8":
|
||||
self.emitByte(MulInt8)
|
||||
of "AddUInt64":
|
||||
self.emitByte(AddUInt64)
|
||||
of "SubUInt64":
|
||||
self.emitByte(SubUInt64)
|
||||
of "DivUInt64":
|
||||
self.emitByte(DivUInt64)
|
||||
of "MulUInt64":
|
||||
self.emitByte(MulUInt64)
|
||||
of "AddUInt32":
|
||||
self.emitByte(AddUInt32)
|
||||
of "SubUInt32":
|
||||
self.emitByte(SubUInt32)
|
||||
of "DivUInt32":
|
||||
self.emitByte(DivUInt32)
|
||||
of "MulUInt32":
|
||||
self.emitByte(MulUInt32)
|
||||
of "AddUInt16":
|
||||
self.emitByte(AddUInt16)
|
||||
of "SubUInt16":
|
||||
self.emitByte(SubUInt16)
|
||||
of "DivUInt16":
|
||||
self.emitByte(DivUInt16)
|
||||
of "MulUInt16":
|
||||
self.emitByte(MulUInt16)
|
||||
of "AddUInt8":
|
||||
self.emitByte(AddUInt8)
|
||||
of "SubUInt8":
|
||||
self.emitByte(SubUInt8)
|
||||
of "DivUInt8":
|
||||
self.emitByte(DivUInt8)
|
||||
of "MulUInt8":
|
||||
self.emitByte(MulUInt8)
|
||||
of "AddFloat64":
|
||||
self.emitByte(AddInt8)
|
||||
of "SubFloat64":
|
||||
self.emitByte(SubInt8)
|
||||
of "DivFloat64":
|
||||
self.emitByte(DivInt8)
|
||||
of "MulFloat64":
|
||||
self.emitByte(MulInt8)
|
||||
of "AddFloat32":
|
||||
self.emitByte(AddFloat32)
|
||||
of "SubFloat32":
|
||||
self.emitByte(SubFloat32)
|
||||
of "DivFloat32":
|
||||
self.emitByte(DivFloat32)
|
||||
of "MulFloat32":
|
||||
self.emitByte(MulFloat32)
|
||||
else:
|
||||
discard # Unreachable
|
||||
|
||||
|
||||
proc generateCall(self: Compiler, fn: Name, args: seq[Expression]) =
|
||||
## Small wrapper that abstracts emitting a call instruction
|
||||
## for a given function
|
||||
if fn.isBuiltinFunction:
|
||||
self.handleBuiltinFunction(fn, args)
|
||||
return
|
||||
self.emitFunction(fn)
|
||||
self.emitByte(LoadReturnAddress)
|
||||
let pos = self.chunk.code.len()
|
||||
|
@ -834,6 +930,7 @@ proc generateCall(self: Compiler, fn: Name, args: seq[Expression]) =
|
|||
proc generateObjCall(self: Compiler, args: seq[Expression]) =
|
||||
## Small wrapper that abstracts emitting a call instruction
|
||||
## for a given function already loaded on the operand stack
|
||||
|
||||
self.emitByte(PushC) # Pops the function off the operand stack onto the call stack
|
||||
self.emitByte(LoadReturnAddress)
|
||||
let pos = self.chunk.code.len()
|
||||
|
@ -1263,7 +1360,10 @@ proc callExpr(self: Compiler, node: CallExpr) =
|
|||
if not funct.isNil():
|
||||
self.generateCall(funct, argExpr)
|
||||
else:
|
||||
self.generateObjCall(argExpr)
|
||||
if funct.isBuiltinFunction:
|
||||
self.handleBuiltinFunction(funct, argExpr)
|
||||
else:
|
||||
self.generateObjCall(argExpr)
|
||||
if self.scopeDepth > 0 and not self.checkCallIsPure(node.callee):
|
||||
if not self.currentFunction.name.isNil():
|
||||
self.error(&"cannot make sure that calls to '{self.currentFunction.name.token.lexeme}' are side-effect free")
|
||||
|
@ -1529,28 +1629,65 @@ proc typeDecl(self: Compiler, node: TypeDecl) =
|
|||
|
||||
|
||||
proc handleMagicPragma(self: Compiler, pragma: Pragma, node: ASTNode) =
|
||||
## Handles the "magic" pragma
|
||||
## Handles the "magic" pragma. Assumes the given name is already
|
||||
## declared
|
||||
if pragma.args.len() != 1:
|
||||
self.error("'magic' pragma: wrong number of arguments")
|
||||
elif pragma.args[0].kind != strExpr:
|
||||
self.error("'magic' pragma: wrong type of argument (string expected)")
|
||||
elif node.kind != NodeKind.funDecl:
|
||||
self.error("'magic' pragma is not valid in this context")
|
||||
var node = FunDecl(node)
|
||||
var fn = self.resolve(node.name)
|
||||
fn.isBuiltinFunction = true
|
||||
fn.builtinOp = pragma.args[0].token.lexeme[1..^2]
|
||||
|
||||
|
||||
proc handlePurePragma(self: Compiler, pragma: Pragma, node: ASTNode) =
|
||||
## Handles the "pure" pragma
|
||||
case node.kind:
|
||||
of funDecl:
|
||||
FunDecl(node).isPure = true
|
||||
of lambdaExpr:
|
||||
LambdaExpr(node).isPure = true
|
||||
else:
|
||||
self.error("'pure' pragma: invalid usage")
|
||||
|
||||
|
||||
proc dispatchPragmas(self: Compiler, node: ASTnode) =
|
||||
## Dispatches pragmas bound to objects
|
||||
var pragmas: seq[Pragma] = @[]
|
||||
case node.kind:
|
||||
of funDecl, NodeKind.typeDecl, NodeKind.varDecl:
|
||||
pragmas = Declaration(node).pragmas
|
||||
of lambdaExpr:
|
||||
pragmas = LambdaExpr(node).pragmas
|
||||
else:
|
||||
discard # Unreachable
|
||||
for pragma in pragmas:
|
||||
if pragma.name.token.lexeme notin self.compilerProcs:
|
||||
self.error(&"unknown pragma '{pragma.name.token.lexeme}'")
|
||||
self.compilerProcs[pragma.name.token.lexeme](self, pragma, node)
|
||||
|
||||
|
||||
proc funDecl(self: Compiler, node: FunDecl) =
|
||||
## Compiles function declarations
|
||||
var function = self.currentFunction
|
||||
self.declareName(node)
|
||||
self.frames.add(self.names.high())
|
||||
self.dispatchPragmas(node)
|
||||
let fn = self.names[^(node.arguments.len() + 1)]
|
||||
# A function's code is just compiled linearly
|
||||
# and then jumped over
|
||||
let jmp = self.emitJump(JumpForwards)
|
||||
# Function's code starts after the jump
|
||||
fn.codePos = self.chunk.code.len()
|
||||
for argument in node.arguments:
|
||||
# Pops off the operand stack onto the
|
||||
# call stack
|
||||
self.emitByte(LoadArgument)
|
||||
var jmp: int
|
||||
if not fn.isBuiltinFunction:
|
||||
self.frames.add(self.names.high())
|
||||
# A function's code is just compiled linearly
|
||||
# and then jumped over
|
||||
jmp = self.emitJump(JumpForwards)
|
||||
# Function's code starts after the jump
|
||||
fn.codePos = self.chunk.code.len()
|
||||
for argument in node.arguments:
|
||||
# Pops off the operand stack onto the
|
||||
# call stack
|
||||
self.emitByte(LoadArgument)
|
||||
if not node.returnType.isNil() and self.inferType(node.returnType).isNil():
|
||||
# Are we returning a generic type?
|
||||
var isGeneric = false
|
||||
|
@ -1566,11 +1703,8 @@ proc funDecl(self: Compiler, node: FunDecl) =
|
|||
self.error(&"cannot infer the type of '{node.returnType.token.lexeme}'")
|
||||
# TODO: Forward declarations
|
||||
if not node.body.isNil():
|
||||
if BlockStmt(node.body).code.len() == 0:
|
||||
if node.pragmas.len() > 0:
|
||||
discard
|
||||
else:
|
||||
self.error("cannot declare function with empty body")
|
||||
if BlockStmt(node.body).code.len() == 0 and not fn.isBuiltinFunction:
|
||||
self.error("cannot declare function with empty body")
|
||||
let fnType = self.inferType(node)
|
||||
let impl = self.findByType(node.name.token.lexeme, fnType)
|
||||
if impl.len() > 1:
|
||||
|
@ -1583,67 +1717,68 @@ proc funDecl(self: Compiler, node: FunDecl) =
|
|||
# We store the current function
|
||||
self.currentFunction = node
|
||||
|
||||
# Since the deferred array is a linear
|
||||
# sequence of instructions and we want
|
||||
# to keep track to whose function's each
|
||||
# set of deferred instruction belongs,
|
||||
# we record the length of the deferred
|
||||
# array before compiling the function
|
||||
# and use this info later to compile
|
||||
# the try/finally block with the deferred
|
||||
# code
|
||||
var deferStart = self.deferred.len()
|
||||
# We let our debugger know a function is starting
|
||||
let start = self.chunk.code.high()
|
||||
self.beginScope()
|
||||
for decl in BlockStmt(node.body).code:
|
||||
self.declaration(decl)
|
||||
var typ: Type
|
||||
var hasVal: bool = false
|
||||
case self.currentFunction.kind:
|
||||
of NodeKind.funDecl:
|
||||
typ = self.inferType(self.currentFunction)
|
||||
hasVal = self.currentFunction.hasExplicitReturn
|
||||
of NodeKind.lambdaExpr:
|
||||
typ = self.inferType(LambdaExpr(Declaration(self.currentFunction)))
|
||||
hasVal = LambdaExpr(Declaration(self.currentFunction)).hasExplicitReturn
|
||||
if not fn.isBuiltinFunction:
|
||||
# Since the deferred array is a linear
|
||||
# sequence of instructions and we want
|
||||
# to keep track to whose function's each
|
||||
# set of deferred instruction belongs,
|
||||
# we record the length of the deferred
|
||||
# array before compiling the function
|
||||
# and use this info later to compile
|
||||
# the try/finally block with the deferred
|
||||
# code
|
||||
var deferStart = self.deferred.len()
|
||||
# We let our debugger know a function is starting
|
||||
let start = self.chunk.code.high()
|
||||
self.beginScope()
|
||||
for decl in BlockStmt(node.body).code:
|
||||
self.declaration(decl)
|
||||
var typ: Type
|
||||
var hasVal: bool = false
|
||||
case self.currentFunction.kind:
|
||||
of NodeKind.funDecl:
|
||||
typ = self.inferType(self.currentFunction)
|
||||
hasVal = self.currentFunction.hasExplicitReturn
|
||||
of NodeKind.lambdaExpr:
|
||||
typ = self.inferType(LambdaExpr(Declaration(self.currentFunction)))
|
||||
hasVal = LambdaExpr(Declaration(self.currentFunction)).hasExplicitReturn
|
||||
else:
|
||||
discard # Unreachable
|
||||
if hasVal and self.currentFunction.returnType.isNil() and not typ.returnType.isNil():
|
||||
self.error("non-empty return statement is not allowed in void functions")
|
||||
elif not hasVal and not self.currentFunction.returnType.isNil():
|
||||
self.error("function has an explicit return type, but no return statement was found")
|
||||
self.endFunctionBeforeReturn()
|
||||
hasVal = hasVal and not typ.returnType.isNil()
|
||||
self.endScope(deleteNames=true, fromFunc=true)
|
||||
# Terminates the function's context
|
||||
self.emitByte(OpCode.Return)
|
||||
if hasVal:
|
||||
self.emitByte(1)
|
||||
else:
|
||||
discard # Unreachable
|
||||
if hasVal and self.currentFunction.returnType.isNil() and not typ.returnType.isNil():
|
||||
self.error("non-empty return statement is not allowed in void functions")
|
||||
elif not hasVal and not self.currentFunction.returnType.isNil():
|
||||
self.error("function has an explicit return type, but no return statement was found")
|
||||
self.endFunctionBeforeReturn()
|
||||
hasVal = hasVal and not typ.returnType.isNil()
|
||||
self.endScope(deleteNames=true, fromFunc=true)
|
||||
# Terminates the function's context
|
||||
self.emitByte(OpCode.Return)
|
||||
if hasVal:
|
||||
self.emitByte(1)
|
||||
else:
|
||||
self.emitByte(0)
|
||||
# Function is ending!
|
||||
self.chunk.cfi.add(start.toTriple())
|
||||
self.chunk.cfi.add(self.chunk.code.high().toTriple())
|
||||
self.chunk.cfi.add(self.frames[^1].toTriple())
|
||||
self.chunk.cfi.add(uint8(node.arguments.len()))
|
||||
if not node.name.isNil():
|
||||
self.chunk.cfi.add(node.name.token.lexeme.len().toDouble())
|
||||
var s = node.name.token.lexeme
|
||||
if node.name.token.lexeme.len() >= uint16.high().int:
|
||||
s = node.name.token.lexeme[0..uint16.high()]
|
||||
self.chunk.cfi.add(s.toBytes())
|
||||
else:
|
||||
self.chunk.cfi.add(0.toDouble())
|
||||
# Currently defer is not functional so we
|
||||
# just pop the instructions
|
||||
for i in countup(deferStart, self.deferred.len() - 1, 1):
|
||||
self.deferred.delete(i)
|
||||
self.emitByte(0)
|
||||
# Function is ending!
|
||||
self.chunk.cfi.add(start.toTriple())
|
||||
self.chunk.cfi.add(self.chunk.code.high().toTriple())
|
||||
self.chunk.cfi.add(self.frames[^1].toTriple())
|
||||
self.chunk.cfi.add(uint8(node.arguments.len()))
|
||||
if not node.name.isNil():
|
||||
self.chunk.cfi.add(node.name.token.lexeme.len().toDouble())
|
||||
var s = node.name.token.lexeme
|
||||
if node.name.token.lexeme.len() >= uint16.high().int:
|
||||
s = node.name.token.lexeme[0..uint16.high()]
|
||||
self.chunk.cfi.add(s.toBytes())
|
||||
else:
|
||||
self.chunk.cfi.add(0.toDouble())
|
||||
# Currently defer is not functional so we
|
||||
# just pop the instructions
|
||||
for i in countup(deferStart, self.deferred.len() - 1, 1):
|
||||
self.deferred.delete(i)
|
||||
|
||||
self.patchJump(jmp)
|
||||
# This makes us compile nested functions correctly
|
||||
self.patchJump(jmp)
|
||||
# This makes us compile nested functions correctly
|
||||
discard self.frames.pop()
|
||||
self.currentFunction = function
|
||||
discard self.frames.pop()
|
||||
|
||||
|
||||
proc patchReturnAddress(self: Compiler, pos: int) =
|
||||
|
|
|
@ -123,6 +123,14 @@ type
|
|||
DivUInt16,
|
||||
DivInt8,
|
||||
DivUInt8,
|
||||
AddFloat64,
|
||||
SubFloat64,
|
||||
DivFloat64,
|
||||
MulFloat64,
|
||||
AddFloat32,
|
||||
SubFloat32,
|
||||
DivFloat32,
|
||||
MulFloat32,
|
||||
## Basic stack operations
|
||||
Pop, # Pops an element off the stack and discards it
|
||||
PopRepl, # Same as Pop, but also prints the value of what's popped (used in REPL mode)
|
||||
|
@ -184,7 +192,10 @@ const simpleInstructions* = {Return, LoadNil,
|
|||
MulUInt16, MulInt8, MulUInt8,
|
||||
DivInt64, DivUInt64, DivInt32,
|
||||
DivUInt32, DivInt16, DivUInt16,
|
||||
DivInt8, DivUInt8
|
||||
DivInt8, DivUInt8, AddFloat64,
|
||||
SubFloat64, DivFloat64, MulFloat64,
|
||||
AddFloat32, SubFloat32, DivFloat32,
|
||||
MulFloat32
|
||||
}
|
||||
|
||||
# Constant instructions are instructions that operate on the bytecode constant table
|
||||
|
|
|
@ -1226,7 +1226,7 @@ proc declaration(self: Parser): Declaration =
|
|||
|
||||
proc parse*(self: Parser, tokens: seq[Token], file: string): seq[Declaration] =
|
||||
## Parses a sequence of tokens into a sequence of AST nodes
|
||||
self.tokens = @[]
|
||||
self.tokens = tokens
|
||||
self.file = file
|
||||
self.current = 0
|
||||
self.currentLoop = LoopContext.None
|
||||
|
|
|
@ -2,192 +2,200 @@
|
|||
|
||||
|
||||
operator `+`(a, b: int): int {
|
||||
#pragma[magic: AddInt64, pure]
|
||||
return;
|
||||
#pragma[magic: "AddInt64", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `+`(a, b: uint): uint {
|
||||
#pragma[magic: AddUInt64, pure]
|
||||
return;
|
||||
operator `+`(a, b: uint64): uint64 {
|
||||
#pragma[magic: "AddUInt64", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `+`(a, b: int32): int32 {
|
||||
#pragma[magic: AddInt32, pure]
|
||||
return;
|
||||
#pragma[magic: "AddInt32", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `+`(a, b: uint32): uint32 {
|
||||
#pragma[magic: AddUInt32, pure]
|
||||
return;
|
||||
#pragma[magic: "AddUInt32", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `+`(a, b: int16): int16 {
|
||||
#pragma[magic: AddInt16, pure]
|
||||
return;
|
||||
#pragma[magic: "AddInt16", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `+`(a, b: uint16): uint16 {
|
||||
#pragma[magic: AddUInt16, pure]
|
||||
return;
|
||||
#pragma[magic: "AddUInt16", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `+`(a, b: int8): int8 {
|
||||
#pragma[magic: AddInt8, pure]
|
||||
return;
|
||||
#pragma[magic: "AddInt8", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `+`(a, b: uint8): uint8 {
|
||||
#pragma[magic: AddUInt8, pure]
|
||||
return;
|
||||
#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]
|
||||
return;
|
||||
#pragma[magic: "SubInt64", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `-`(a, b: uint): uint {
|
||||
#pragma[magic: SubUInt64, pure]
|
||||
return;
|
||||
operator `-`(a, b: uint64): uint64 {
|
||||
#pragma[magic: "SubUInt64", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `-`(a, b: int32): int32 {
|
||||
#pragma[magic: SubInt32, pure]
|
||||
return;
|
||||
#pragma[magic: "SubInt32", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `-`(a, b: uint32): uint32 {
|
||||
#pragma[magic: SubUInt32, pure]
|
||||
return;
|
||||
#pragma[magic: "SubUInt32", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `-`(a, b: int16): int16 {
|
||||
#pragma[magic: SubInt16, pure]
|
||||
return;
|
||||
#pragma[magic: "SubInt16", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `-`(a, b: uint16): uint16 {
|
||||
#pragma[magic: SubUInt16, pure]
|
||||
return;
|
||||
#pragma[magic: "SubUInt16", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `-`(a, b: int8): int8 {
|
||||
#pragma[magic: SubInt8, pure]
|
||||
return;
|
||||
#pragma[magic: "SubInt8", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `-`(a, b: uint8): uint8 {
|
||||
#pragma[magic: SubUInt8, pure]
|
||||
return;
|
||||
#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]
|
||||
return;
|
||||
#pragma[magic: "MulInt64", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `*`(a, b: uint): uint {
|
||||
#pragma[magic: MulUInt64, pure]
|
||||
return;
|
||||
operator `*`(a, b: uint64): uint64 {
|
||||
#pragma[magic: "MulUInt64", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `*`(a, b: int32): int32 {
|
||||
#pragma[magic: MulInt32, pure]
|
||||
return;
|
||||
#pragma[magic: "MulInt32", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `*`(a, b: uint32): uint32 {
|
||||
#pragma[magic: MulUInt32, pure]
|
||||
return;
|
||||
#pragma[magic: "MulUInt32", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `*`(a, b: int16): int16 {
|
||||
#pragma[magic: MulInt16, pure]
|
||||
return;
|
||||
#pragma[magic: "MulInt16", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `*`(a, b: uint16): uint16 {
|
||||
#pragma[magic: MulUInt16, pure]
|
||||
return;
|
||||
#pragma[magic: "MulUInt16", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `*`(a, b: int8): int8 {
|
||||
#pragma[magic: MulInt8, pure]
|
||||
return;
|
||||
#pragma[magic: "MulInt8", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `*`(a, b: uint8): uint8 {
|
||||
#pragma[magic: MulUInt8, pure]
|
||||
return;
|
||||
#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]
|
||||
return;
|
||||
#pragma[magic: "DivInt64", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `/`(a, b: uint): uint {
|
||||
#pragma[magic: DivUInt64, pure]
|
||||
return;
|
||||
operator `/`(a, b: uint64): uint64 {
|
||||
#pragma[magic: "DivUInt64", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `/`(a, b: int32): int32 {
|
||||
#pragma[magic: DivInt32, pure]
|
||||
return;
|
||||
#pragma[magic: "DivInt32", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `/`(a, b: uint32): uint32 {
|
||||
#pragma[magic: DivUInt32, pure]
|
||||
return;
|
||||
#pragma[magic: "DivUInt32", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `/`(a, b: int16): int16 {
|
||||
#pragma[magic: DivInt16, pure]
|
||||
return;
|
||||
#pragma[magic: "DivInt16", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `/`(a, b: uint16): uint16 {
|
||||
#pragma[magic: DivUInt16, pure]
|
||||
return;
|
||||
#pragma[magic: "DivUInt16", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `/`(a, b: int8): int8 {
|
||||
#pragma[magic: DivInt8, pure]
|
||||
return;
|
||||
#pragma[magic: "DivInt8", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `/`(a, b: uint8): uint8 {
|
||||
#pragma[magic: DivUInt8, pure]
|
||||
return;
|
||||
}
|
||||
#pragma[magic: "DivUInt8", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `/`(a, b: float64): float64 {
|
||||
#pragma[magic: "DivFloat64", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `/`(a, b: float32): float32 {
|
||||
#pragma[magic: "DivFloat32", pure]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue