From 875440ba8cb4eeef663bf5293f7c4d4566608284 Mon Sep 17 00:00:00 2001 From: nocturn9x Date: Tue, 5 Jan 2021 09:35:18 +0100 Subject: [PATCH] Made print a variadic function and added clock() for benchmarking --- examples/fib.jpl | 2 +- src/japl.nim | 3 ++- src/stdlib.nim | 44 +++++++++++++++++++++++++++++++++++++++++--- src/vm.nim | 8 +++++--- 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/examples/fib.jpl b/examples/fib.jpl index 994811d..fc0cbc8 100644 --- a/examples/fib.jpl +++ b/examples/fib.jpl @@ -6,4 +6,4 @@ fun fib(n) { } -fib(20); //TODO: Benchmark this +print(fib(15)); //TODO: Benchmark this diff --git a/src/japl.nim b/src/japl.nim index 5322818..95dba20 100644 --- a/src/japl.nim +++ b/src/japl.nim @@ -25,7 +25,7 @@ import stdlib proc repl() = var bytecodeVM = initVM() - stdlibInit(bytecodeVM) + bytecodeVM.stdlibInit() echo JAPL_VERSION_STRING echo &"[Nim {NimVersion} on {hostOs} ({hostCPU})]" when DEBUG_TRACE_VM: @@ -75,6 +75,7 @@ proc main(file: string = "") = except IOError: echo &"Error: '{file}' could not be read, probably you don't have the permission to read it" var bytecodeVM = initVM() + bytecodeVM.stdlibInit() when DEBUG_TRACE_VM: echo "Debugger enabled, expect verbose output\n" echo "==== VM Constants ====\n" diff --git a/src/stdlib.nim b/src/stdlib.nim index f06bac2..531c9a3 100644 --- a/src/stdlib.nim +++ b/src/stdlib.nim @@ -1,15 +1,53 @@ +# Copyright 2020 Mattia Giambirtone +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. -# this implements stdlib functions for JAPL +# Implementations of builtin functions and modules import vm import types/native import types/baseObject import types/japlNil +import types/numbers import types/methods +import times + + proc natPrint(args: seq[ptr Obj]): tuple[ok: bool, result: ptr Obj] = - echo args[0].stringify() + ## Native function print + ## Prints an object representation + ## to stdout. If more than one argument + ## is passed, they will be printed separated + ## by a space + var res = "" + for arg in args: + res = res & arg.stringify() & " " + echo res return (ok: true, result: asNil()) + +proc natClock(args: seq[ptr Obj]): tuple[ok: bool, result: ptr Obj] = + ## Native function clock + ## Returns the current unix + ## time (also known as epoch) + ## with subsecond precision + + # TODO: Move this to a separate module once we have imports + + result = (ok: true, result: getTime().toUnixFloat().asFloat()) + + template stdlibInit*(vm: VM) = - vm.defineGlobal("print", newNative("print", natPrint, 1)) + vm.defineGlobal("print", newNative("print", natPrint, -1)) + vm.defineGlobal("clock", newNative("clock", natClock, 0)) diff --git a/src/vm.nim b/src/vm.nim index 9c64571..30e3202 100644 --- a/src/vm.nim +++ b/src/vm.nim @@ -231,8 +231,9 @@ proc call(self: var VM, function: ptr Function, argCount: int): bool = self.frameCount += 1 return true + proc call(self: var VM, native: ptr Native, argCount: int): bool = - if argCount != native.arity: + if argCount != native.arity and native.arity != -1: self.error(newTypeError(&"function '{stringify(native.name)}' takes {native.arity} argument(s), got {argCount}")) return false let slot = self.stack.high() - argCount + 1 @@ -242,14 +243,15 @@ proc call(self: var VM, native: ptr Native, argCount: int): bool = let nativeResult = native.nimproc(args) if not nativeResult.ok: self.error(cast[ptr JaplException](nativeResult.result)) - # assumes that all native procs behave well, and if not ok, they + # assumes that all native procs behave well, and if not ok, they # only return japl exceptions for i in countup(slot - 1, self.stack.high()): discard self.pop() # TODO once stack is a custom datatype, # just reduce its length - self.push(nativeResult.result) + self.push(nativeResult.result) return true + proc callObject(self: var VM, callee: ptr Obj, argCount: uint8): bool = ## Wrapper around call() to do type checking if callee.isCallable():