Getting closer to compilability

This commit is contained in:
Productive2 2020-10-23 17:14:55 +02:00
parent 0df6838941
commit 9d13f53e6d
13 changed files with 71 additions and 44 deletions

View File

@ -16,9 +16,9 @@
import tables
import strutils
import meta/tokenobject
import meta/japlvalue
import types/stringtype
import types/functiontype
import types/japlvalue
import types/string
import types/function
const FRAMES_MAX* = 400 # TODO: Inspect why the VM crashes if this exceeds 400

View File

@ -20,14 +20,13 @@ import algorithm
import strformat
import lexer
import common
import meta/chunk
import meta/opcode
import meta/tokenobject
import meta/valueobject
import meta/tokentype
import meta/looptype
import types/stringtype
import types/functiontype
import types/objecttype
import types/japlvalue
import types/string
import types/function
import tables
when isMainModule:
import util/debug
@ -177,7 +176,7 @@ proc makeLongConstant(self: ref Compiler, val: Value): array[3, uint8] =
proc emitConstant(self: ref Compiler, value: Value) =
## Emits a Constant or ConstantLong instruction along
## with its operand
if self.currentChunk().consts.values.len > 255:
if self.currentChunk().consts.len > 255:
self.emitByte(OpCode.ConstantLong)
self.emitBytes(self.makeLongConstant(value))
else:
@ -581,7 +580,7 @@ proc varDeclaration(self: ref Compiler) =
var shortName: uint8
var longName: array[3, uint8]
var useShort: bool = true
if self.currentChunk.consts.values.len < 255:
if self.currentChunk.consts.len < 255:
shortName = self.parseVariable("Expecting variable name")
else:
useShort = false
@ -617,7 +616,7 @@ proc deleteVariable(self: ref Compiler, canAssign: bool) =
else:
code = OpCode.DeleteLocal
self.localCount = self.localCount - 1
if self.currentChunk.consts.values.len < 255:
if self.currentChunk.consts.len < 255:
var name = self.identifierConstant(self.parser.previous())
self.emitBytes(code, name)
else:
@ -900,7 +899,7 @@ proc parseFunction(self: ref Compiler, funType: FunctionType) =
self.parseBlock()
var fun = self.endCompiler()
self = self.enclosing
if self.currentChunk.consts.values.len < 255:
if self.currentChunk.consts.len < 255:
self.emitBytes(OpCode.Constant, self.makeConstant(Value(kind: OBJECT, obj: fun)))
else:
self.emitByte(OpCode.ConstantLong)

View File

@ -29,7 +29,8 @@ import strformat
import tables
import meta/tokentype
import meta/tokenobject
import meta/valueobject
import types/string
import types/japlvalue
# Table of all tokens except reserved keywords
const TOKENS = to_table({

View File

@ -23,7 +23,7 @@
import segfaults
import meta/japlvalue
import types/japlvalue
proc reallocate*(pointr: pointer, oldSize: int, newSize: int): pointer =

View File

@ -15,7 +15,7 @@
## The module dedicated to the Chunk type
## A chunk is a piece of bytecode.
import japlvalue
import ../types/japlvalue
type
OpCode* {.pure.} = enum

View File

@ -13,7 +13,7 @@
# limitations under the License.
import tokentype
import japlvalue
import ../types/japlvalue
# Token object

View File

@ -15,8 +15,8 @@
## Defines JAPL exceptions
import objecttype
import stringtype
import string
import japlvalue
import strformat
import ../memory
@ -24,6 +24,8 @@ import ../memory
proc stringify*(self: ptr JAPLException): string =
return &"{self.errName.stringify}: {self.message.stringify}"
proc isFalsey*(self: ptr JAPLException): bool =
return false
proc newTypeError*(message: string): ptr JAPLException =
result = allocateObj(JAPLException, ObjectType.Exception)

View File

@ -19,11 +19,11 @@
# code objects that can be compiled inside the JAPL runtime, pretty much
# like in Python
import stringtype
import string
import strformat
import ../memory
import ../meta/opcode
import ../meta/japlvalue
import japlvalue
import tables

View File

@ -67,7 +67,7 @@ type
name*: ptr String
arity*: int
optionals*: int
defaults*: Table[string, Obj]
defaults*: Table[string, Value]
chunk*: Chunk
JAPLException* = object of Obj
errName*: ptr String

View File

@ -1,3 +1,22 @@
# 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.
import japlvalue
import string
import function
import exceptions
import strutils
func stringify*(value: Value): string =
case value.kind:
@ -53,21 +72,24 @@ func bool*(value: Value): bool =
of ValueType.Nan:
result = true
func typeName*(obj: ptr Obj): string =
case obj.kind:
of ObjectType.String:
result = cast[ptr String](obj).typeName()
of ObjectType.Function:
result = cast[ptr Function](obj).typeName()
else:
result = "" # TODO unimplemented
func typeName*(value: Value): string =
case value.kind:
of ValueType.Bool, ValueType.Nil, ValueType.Double,
ValueType.Integer, ValueType.Nan, ValueType.Inf:
result = ($value.kind).toLowerAscii()
of ValueType.Minf:
result = "inf"
result = "inf"
of ValueType.Object:
case value.obj.kind:
of ObjectType.String:
result = cast[ptr String](value.obj).typeName()
of ObjectType.Function:
result = cast[ptr Function](value.obj).typeName()
else:
result = value.obj.typeName()
result = typeName(value.obj)
proc eq*(a: Value, b: Value): bool =
if a.kind != b.kind:
@ -87,13 +109,14 @@ proc eq*(a: Value, b: Value): bool =
of ObjectType.String:
var a = cast[ptr String](a.obj)
var b = cast[ptr String](b.obj)
result = valuesEqual(a, b)
result = eq(a, b)
of ObjectType.Function:
var a = cast[ptr Function](a.obj)
var b = cast[ptr Function](b.obj)
result = valuesEqual(a, b)
result = eq(a, b)
else:
result = valuesEqual(a.obj, b.obj)
result = false # TODO unimplemented
of ValueType.Inf:
result = b.kind == ValueType.Inf
of ValueType.Minf:

View File

@ -17,7 +17,7 @@
# therefore immutable from the user's perspective. They are
# natively ASCII encoded, but soon they will support for unicode.
import ../meta/japlvalue
import japlvalue
import strformat
import ../memory

View File

@ -15,7 +15,9 @@
## This module takes chunks of bytecode, and prints their contents to the
## screen.
import ../meta/chunk
import ../meta/opcode
import ../types/japlvalue
import ../types/operations
import ../common
import strformat
@ -38,7 +40,7 @@ proc constantLongInstruction(name: string, chunk: Chunk, offset: int): int =
var constant: int
copyMem(constant.addr, unsafeAddr(constantArray), sizeof(constantArray))
echo &"\tInstruction at IP: {name}, points to slot {constant}"
let obj = chunk.consts.values[constant]
let obj = chunk.consts[constant]
echo &"\tOperand: {stringify(obj)}\n\tValue kind: {obj.kind}\n"
return offset + 4
@ -46,7 +48,7 @@ proc constantLongInstruction(name: string, chunk: Chunk, offset: int): int =
proc constantInstruction(name: string, chunk: Chunk, offset: int): int =
var constant = chunk.code[offset + 1]
echo &"\tInstruction at IP: {name}, points to index {constant}"
let obj = chunk.consts.values[constant]
let obj = chunk.consts[constant]
echo &"\tOperand: {stringify(obj)}\n\tValue kind: {obj.kind}\n"
return offset + 2

16
vm.nim
View File

@ -24,12 +24,12 @@ import lenientops
import common
import compiler
import tables
import meta/chunk
import meta/valueobject
import meta/opcode
import types/exceptions
import types/objecttype
import types/stringtype
import types/functiontype
import types/japlvalue
import types/string
import types/function
import types/operations
import memory
when DEBUG_TRACE_VM:
import util/debug
@ -169,9 +169,9 @@ proc sliceRange(self: var VM): bool =
of ObjectType.String:
var str = popped.toStr()
if sliceEnd.isNil():
sliceEnd = Value(kind: INTEGER, intValue: len(str))
sliceEnd = Value(kind: ValueType.Integer, intValue: len(str))
if sliceStart.isNil():
sliceStart = Value(kind: INTEGER, intValue: 0)
sliceStart = Value(kind: ValueType.Integer, intValue: 0)
elif not sliceStart.isInt() or not sliceEnd.isInt():
self.error(newTypeError("string indeces must be integers"))
return false
@ -183,7 +183,7 @@ proc sliceRange(self: var VM): bool =
self.push(Value(kind: OBJECT, obj: addObject(addr self, newString(""))))
return true
if sliceEnd.toInt() - 1 > len(str) - 1:
sliceEnd = Value(kind: INTEGER, intValue: len(str))
sliceEnd = Value(kind: ValueType.Integer, intValue: len(str))
if sliceStart.toInt() > sliceEnd.toInt():
self.push(Value(kind: OBJECT, obj: addObject(addr self, newString(""))))
return true