Return addresses are now 64 bits long, return statements now compile to jumps, initial (broken) work on generics
This commit is contained in:
parent
807b48bac9
commit
d4d1034cef
|
@ -628,7 +628,7 @@ when debugVM: # So nim shuts up
|
|||
stdout.styledWrite(fgGreen, "Call Stack: ", fgMagenta, "[")
|
||||
for i, e in self.calls:
|
||||
stdout.styledWrite(fgYellow, $e)
|
||||
if i < self.calls.len():
|
||||
if i < self.calls.high():
|
||||
stdout.styledWrite(fgYellow, ", ")
|
||||
styledEcho fgMagenta, "]"
|
||||
if self.operands.len() !> 0:
|
||||
|
@ -724,7 +724,7 @@ proc dispatch*(self: PeonVM) =
|
|||
# Calls a peon function. The calling convention here
|
||||
# is pretty simple: the first value in the frame is
|
||||
# the new instruction pointer to jump to, then a
|
||||
# 32-bit return address follows. After that, all
|
||||
# 64-bit return address follows. After that, all
|
||||
# arguments and locals follow. Note that, due to
|
||||
# how the stack works, all arguments before the call
|
||||
# are in the reverse order in which they are passed
|
||||
|
@ -780,10 +780,6 @@ proc dispatch*(self: PeonVM) =
|
|||
# in a hidden function, so this
|
||||
# will also exit the VM if we're
|
||||
# at the end of the program
|
||||
while self.calls.len().uint64 !> self.frames[^1] + 2'u64:
|
||||
# Discards the function's local variables,
|
||||
# if there is any
|
||||
discard self.popc()
|
||||
let ret = self.popc() # Return address
|
||||
discard self.popc() # Function address
|
||||
if self.readByte() == 1:
|
||||
|
@ -796,7 +792,12 @@ proc dispatch*(self: PeonVM) =
|
|||
if self.frames.len() == 0:
|
||||
# End of the program!
|
||||
return
|
||||
self.ip = ret.uint
|
||||
# We change the instruction
|
||||
# pointer just now because
|
||||
# if we did it beforehand,
|
||||
# our readByte() call would've
|
||||
# read from the wrong offset
|
||||
self.ip = ret
|
||||
of SetResult:
|
||||
# Sets the result of the
|
||||
# current function. A Return
|
||||
|
@ -1023,6 +1024,8 @@ proc dispatch*(self: PeonVM) =
|
|||
# cannot be converted to a date. The number
|
||||
# is in seconds
|
||||
self.push(cast[uint64](getMonoTime().ticks().float() / 1_000_000_000))
|
||||
of LogicalNot:
|
||||
self.push(uint64(not self.pop().bool))
|
||||
else:
|
||||
discard
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -530,7 +530,7 @@ proc parseBackticks(self: Lexer) =
|
|||
## parser complaining about syntax
|
||||
## errors
|
||||
while not self.match("`") and not self.done():
|
||||
if self.peek().isAlphaNumeric() or self.symbols.existsSymbol(self.peek()) or self.peek() in ["&", "|"]:
|
||||
if self.peek().isAlphaNumeric() or self.symbols.existsSymbol(self.peek()):
|
||||
discard self.step()
|
||||
continue
|
||||
self.error(&"unexpected character: '{self.peek()}'")
|
||||
|
|
|
@ -147,7 +147,6 @@ type
|
|||
StoreVar, # Stores the value of b at position a in the stack
|
||||
LoadClosure, # Pushes the object position x in the closure array onto the stack
|
||||
StoreClosure, # Stores the value of b at position a in the closure array
|
||||
LiftArgument, # Closes over a function argument
|
||||
PopClosure,
|
||||
## Looping and jumping
|
||||
Jump, # Absolute, unconditional jump into the bytecode
|
||||
|
@ -175,7 +174,8 @@ type
|
|||
NoOp, # Just a no-op
|
||||
PopC, # Pop off the call stack onto the operand stack
|
||||
PushC, # Pop off the operand stack onto the call stack
|
||||
SysClock64 # Pushes the output of a monotonic clock on the stack
|
||||
SysClock64, # Pushes the output of a monotonic clock on the stack
|
||||
LogicalNot
|
||||
|
||||
|
||||
# We group instructions by their operation/operand types for easier handling when debugging
|
||||
|
@ -239,6 +239,7 @@ const simpleInstructions* = {Return, LoadNil,
|
|||
PrintNan,
|
||||
PrintInf,
|
||||
PrintString,
|
||||
LogicalNot
|
||||
}
|
||||
|
||||
# Constant instructions are instructions that operate on the bytecode constant table
|
||||
|
@ -251,7 +252,7 @@ const constantInstructions* = {LoadInt64, LoadUInt64,
|
|||
|
||||
# Stack triple instructions operate on the stack at arbitrary offsets and pop arguments off of it in the form
|
||||
# of 24 bit integers
|
||||
const stackTripleInstructions* = {StoreVar, LoadVar, LoadCLosure, LiftArgument, PopClosure}
|
||||
const stackTripleInstructions* = {StoreVar, LoadVar, LoadCLosure, PopClosure}
|
||||
|
||||
# Stack double instructions operate on the stack at arbitrary offsets and pop arguments off of it in the form
|
||||
# of 16 bit integers
|
||||
|
|
|
@ -59,5 +59,5 @@ proc fillSymbolTable*(tokenizer: Lexer) =
|
|||
tokenizer.symbols.addKeyword("ref", TokenType.Ref)
|
||||
tokenizer.symbols.addKeyword("ptr", TokenType.Ptr)
|
||||
for sym in [">", "<", "=", "~", "/", "+", "-", "_", "*", "?", "@", ":", "==", "!=",
|
||||
">=", "<=", "+=", "-=", "/=", "*=", "**=", "!", "%"]:
|
||||
">=", "<=", "+=", "-=", "/=", "*=", "**=", "!", "%", "&", "|", "^"]:
|
||||
tokenizer.symbols.addSymbol(sym, Symbol)
|
|
@ -1,18 +1,11 @@
|
|||
import std;
|
||||
|
||||
operator `+`(a, b: int): int {
|
||||
#pragma[magic: "AddInt64", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `+`(a, b: int32): int32 {
|
||||
#pragma[magic: "AddInt64", pure]
|
||||
}
|
||||
|
||||
|
||||
fn sum[T: int | int32](a, b: T): T {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
sum(1, 2);
|
||||
sum(1'i32, 2'i32);
|
||||
|
||||
# print(sum(1, 2));
|
||||
# print(sum(1'i32, 2'i32));
|
||||
print(sum(1'i16, 2'i16)); # Will not work if uncommented!
|
35
tests/std.pn
35
tests/std.pn
|
@ -535,19 +535,44 @@ operator `or`*(a, b: bool): bool {
|
|||
}
|
||||
|
||||
|
||||
operator `&`*(a, b: bool): bool {
|
||||
#pragma[magic: "LogicalAnd", pure]
|
||||
operator `not`*(a: bool): bool {
|
||||
#pragma[magic: "LogicalNot", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `|`*(a, b: bool): bool {
|
||||
#pragma[magic: "LogicalOr", pure]
|
||||
operator `&`*(a, b: int): bool {
|
||||
#pragma[magic: "And", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `|`*(a, b: int): int {
|
||||
#pragma[magic: "Or", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `~`*(a: int): int {
|
||||
#pragma[magic: "Not", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `>>`*(a, b: int): int {
|
||||
#pragma[magic: "RShift", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `<<`*(a, b: int): int {
|
||||
#pragma[magic: "LShift", pure]
|
||||
}
|
||||
|
||||
|
||||
operator `^`*(a, b: int): int {
|
||||
#pragma[magic: "Xor", pure]
|
||||
}
|
||||
|
||||
|
||||
# Assignment operators
|
||||
|
||||
operator `=`*[T: Any](a: var T, b: T) {
|
||||
operator `=`*[T: all](a: var T, b: T) {
|
||||
#pragma[magic: "GenericAssign"]
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue