Initial work on the type system. Added ImplicitReturn bytecode optimization. Made checkDecl a template instead of a procedure

This commit is contained in:
Nocturn9x 2022-03-21 15:04:45 +01:00
parent 1afe2f2f47
commit 10df2d3c17
7 changed files with 139 additions and 12 deletions

View File

@ -11,9 +11,9 @@
# 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.
# Implementation of a custom list data type for JAPL objects (used also internally by the VM)
{.experimental: "implicitDeref".}
import iterable
import ../../memory/allocator
import baseObject

View File

@ -13,6 +13,8 @@
# limitations under the License.
## The base JAPL object
import ../../memory/allocator
@ -28,7 +30,8 @@ type
## The base object for all
## JAPL types. Every object
## in JAPL implicitly inherits
## from this base type
## from this base type and extends
## its functionality
kind*: ObjectType
hashValue*: uint64
@ -36,7 +39,7 @@ type
## Object constructors and allocators
proc allocateObject*(size: int, kind: ObjectType): ptr Obj =
## Wrapper around memory.reallocate to create a new generic JAPL object
## Wrapper around reallocate() to create a new generic JAPL object
result = cast[ptr Obj](reallocate(nil, 0, size))
result.kind = kind
@ -50,13 +53,32 @@ template allocateObj*(kind: untyped, objType: ObjectType): untyped =
proc newObj*: ptr Obj =
## Allocates a generic JAPL object
result = allocateObj(Obj, ObjectType.BaseObject)
result.hashValue = 0x123FFFF
proc asObj*(self: ptr Obj): ptr Obj =
## Casts a specific JAPL object into a generic
## pointer to Obj
result = cast[ptr Obj](self)
## Default object methods implementations
# In JAPL code, this method will be called
# stringify()
proc `$`*(self: ptr Obj): string = "<object>"
proc stringify*(self: ptr Obj): string = $self
proc hash*(self: ptr Obj): uint64 = 0x123FFFF # Constant hash value
proc `$`*(self: ptr Obj): string = "<object>"
proc hash*(self: ptr Obj): int64 = 0x123FFAA # Constant hash value
# I could've used mul, sub and div, but "div" is a reserved
# keyword and using `div` looks ugly. So to keep everything
# consistent I just made all names long
proc multiply*(self, other: ptr Obj): ptr Obj = nil
proc sum*(self, other: ptr Obj): ptr Obj = nil
proc divide*(self, other: ptr Obj): ptr Obj = nil
proc subtract*(self, other: ptr Obj): ptr Obj = nil
# Returns 0 if self == other, a negative number if self < other
# and a positive number if self > other. This is a convenience
# method to implement all basic comparison operators in one
# method
proc compare*(self, other: ptr Obj): ptr Obj = nil
# Specific methods for each comparison
proc equalTo*(self, other: ptr Obj): ptr Obj = nil
proc greaterThan*(self, other: ptr Obj): ptr Obj = nil
proc lessThan*(self, other: ptr Obj): ptr Obj = nil
proc greaterOrEqual*(self, other: ptr Obj): ptr Obj = nil
proc lessOrEqual*(self, other: ptr Obj): ptr Obj = nil

View File

@ -0,0 +1,49 @@
# Copyright 2022 Mattia Giambirtone & All Contributors
#
# 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.
## Implementation of integer types
import baseObject
import lenientops
type Float* = object of Obj
value: float64
proc newFloat*(value: float): ptr Float =
## Initializes a new JAPL
## float object from
## a machine native float
result = allocateObj(Float, ObjectType.Float)
result.value = value
proc toNativeFloat*(self: ptr Float): float =
## Returns the float's machine
## native underlying value
result = self.value
proc `$`*(self: ptr Float): string = $self.value
proc hash*(self: ptr Float): int64 =
## Implements hashing
## for the given float
if self.value - int(self.value) == self.value:
result = int(self.value)
else:
result = 2166136261 xor int(self.value) # TODO: Improve this
result *= 16777619

View File

@ -0,0 +1,40 @@
# Copyright 2022 Mattia Giambirtone & All Contributors
#
# 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.
## Implementation of integer types
import baseObject
type Integer* = object of Obj
value: int64
proc newInteger*(value: int64): ptr Integer =
## Initializes a new JAPL
## integer object from
## a machine native integer
result = allocateObj(Integer, ObjectType.Integer)
result.value = value
proc toNativeInteger*(self: ptr Integer): int64 =
## Returns the integer's machine
## native underlying value
result = self.value
proc `$`*(self: ptr Integer): string = $self.value
proc hash*(self: ptr Integer): int64 = self.value

View File

@ -0,0 +1,15 @@
# Copyright 2022 Mattia Giambirtone & All Contributors
#
# 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.
# JAPL string implementations

View File

@ -977,7 +977,7 @@ proc funDecl(self: Compiler, node: FunDecl) =
if not self.enableOptimizations:
self.emitBytes(OpCode.Nil, OpCode.Return)
else:
self.emitBytes(ImplicitReturn)
self.emitByte(ImplicitReturn)
# Currently defer is not functional so we
# just pop the instructions

View File

@ -765,7 +765,8 @@ proc forStmt(self: Parser): ASTNode =
# increment variable which doesn't really make sense, but still
# allow people that like verbosity (for *some* reason) to use
# private static var declarations as well as just private var
# and static var
# and static var as well as providing decently specific error
# messages
if self.match(Semicolon):
discard
elif self.match(Dynamic):
@ -839,7 +840,7 @@ proc ifStmt(self: Parser): ASTNode =
result = newIfStmt(condition, thenBranch, elseBranch, tok)
proc checkDecl(self: Parser, isStatic, isPrivate: bool) =
template checkDecl(self: Parser, isStatic, isPrivate: bool) =
## Handy utility function that avoids us from copy
## pasting the same checks to all declaration handlers
if not isStatic and self.currentFunction != nil: