Skip to content

Commit

Permalink
Float support (0.1.7)
Browse files Browse the repository at this point in the history
Merge pull request #7 from ferus-web/float-support
  • Loading branch information
xTrayambak authored Jul 21, 2024
2 parents 5185eaf + ebc3757 commit ea0999a
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 31 deletions.
2 changes: 1 addition & 1 deletion mirage.nimble
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Package

version = "0.1.6"
version = "0.1.7"
author = "xTrayambak"
description = "A nifty bytecode generator and runtime"
license = "MIT"
Expand Down
43 changes: 35 additions & 8 deletions src/mirage/atom.nim
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type
UnsignedInt = 5
Boolean = 6
Object = 7
Float = 8

AtomOverflowError* = object of CatchableError
SequenceError* = object of CatchableError
Expand All @@ -39,9 +40,11 @@ type
of Boolean:
state*: bool
of Object:
fields*: TableRef[string, int]
fields*: Table[string, int]
values*: seq[MAtom]
of Null: discard
of Float:
floatVal*: float64

MAtomSeq* = distinct seq[MAtom]

Expand Down Expand Up @@ -115,6 +118,8 @@ proc hash*(atom: MAtom): Hash {.inline.} =
h = h !& atom.uinteger.hash()
of Boolean:
h = h !& atom.state.hash()
of Float:
h = h !& atom.floatVal.hash()
else: discard

!$h
Expand Down Expand Up @@ -144,8 +149,12 @@ proc crush*(atom: MAtom, id: string, quote: bool = true): string {.inline.} =
result &= ", "

result &= ']' # sequence guard close
of Null, Object:
of Float:
result &= $atom.floatVal
of Null:
return "NULL"
of Object:
return "Object"

proc setCap*(atom: var MAtom, cap: int) {.inline.} =
case atom.kind
Expand Down Expand Up @@ -202,6 +211,10 @@ proc getUint*(atom: MAtom): Option[uint] {.inline.} =
if atom.kind == UnsignedInt:
return some atom.uinteger

proc getFloat*(atom: MAtom): Option[float64] {.inline.} =
if atom.kind == Float:
return some atom.floatVal

proc getSequence*(atom: MAtom): Option[seq[MAtom]] {.inline.} =
if atom.kind == Sequence:
return some(atom.sequence)
Expand Down Expand Up @@ -230,6 +243,12 @@ proc boolean*(b: bool): MAtom {.inline, gcsafe, noSideEffect.} =
state: b
)

proc floating*(value: float64): MAtom {.inline, gcsafe, noSideEffect.} =
MAtom(
kind: Float,
floatVal: value
)

proc boolean*(s: string): Option[MAtom] {.inline, gcsafe, noSideEffect.} =
try:
return some(
Expand All @@ -255,7 +274,7 @@ proc sequence*(s: seq[MAtom]): MAtom {.inline.} =
proc obj*: MAtom {.inline.} =
MAtom(
kind: Object,
fields: newTable[string, int](),
fields: initTable[string, int](),
values: @[]
)

Expand All @@ -265,23 +284,23 @@ proc toString*(atom: MAtom): MAtom {.inline.} =
return atom
of Ident:
return str(
$(&atom.getIdent())
atom.ident
)
of Integer:
return str(
$(&atom.getInt())
$atom.integer
)
of Sequence:
return str(
$(&atom.getSequence())
$atom.sequence
)
of UnsignedInt:
return str(
$(&atom.getUint())
$atom.uinteger
)
of Boolean:
return str(
$(&atom.getBool())
$atom.state
)
of Object:
var msg = "<object structure>\n"
Expand All @@ -291,6 +310,10 @@ proc toString*(atom: MAtom): MAtom {.inline.} =

msg &= "<end object structure>"
return msg.str()
of Float:
return str(
$atom.floatVal
)
of Null:
return str "Null"

Expand All @@ -314,4 +337,8 @@ proc toInt*(atom: MAtom): MAtom {.inline.} =
return integer 0
of Boolean:
return atom.state.int.integer()
of Float:
return integer(
atom.floatVal.int
)
of Object: return integer 0
2 changes: 1 addition & 1 deletion src/mirage/runtime/pulsar/bytecodeopsetconv.nim
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ proc nextOperation*(dtok: var Tokenizer): Option[Operation] {.inline.} =
while not dtok.isEof():
let arg = dtok.next()

if arg.kind in [tkQuotedString, tkInteger, tkIdent]:
if arg.kind in [tkQuotedString, tkInteger, tkDouble, tkIdent]:
op.rawArgs.add(arg)
continue

Expand Down
13 changes: 13 additions & 0 deletions src/mirage/runtime/pulsar/interpreter.nim
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,12 @@ proc resolve*(

op.arguments &=
op.consume(Integer, "MOVE expects an integer at position 2")
of LoadFloat:
op.arguments &=
op.consume(Integer, "LOADF expects an integer at position 1")

op.arguments &=
op.consume(Float, "LOADF expects an integer at position 2")

op.rawArgs = mRawArgs

Expand Down Expand Up @@ -1038,6 +1044,13 @@ proc execute*(interpreter: PulsarInterpreter, op: var Operation) =
`=destroy`(interpreter.stack[src])
interpreter.stack[src] = null()
inc interpreter.currIndex
of LoadFloat:
let
pos = (&op.arguments[0].getInt()).uint
value = op.arguments[1]

interpreter.addAtom(value, pos)
inc interpreter.currIndex
else:
when defined(release):
inc interpreter.currIndex
Expand Down
3 changes: 3 additions & 0 deletions src/mirage/runtime/pulsar/operation.nim
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ proc consume*(
rawType = case raw.kind
of tkQuotedString: String
of tkInteger: Integer
of tkDouble: Float
else: Null

if not *position and operation.rawArgs.len > 1:
Expand All @@ -73,4 +74,6 @@ proc consume*(
return str raw.ident
of tkInteger:
return integer raw.integer
of tkDouble:
return floating raw.double.float64
else: discard
35 changes: 20 additions & 15 deletions src/mirage/runtime/shared.nim
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,9 @@ type
## Move an atom to another position, replacing the source with a NULL atom.
MoveAtom = 0x2a

## Load a float onto a position
LoadFloat = 0x2b

const
OpCodeToTable* = {
"CALL": Call,
Expand Down Expand Up @@ -242,27 +245,29 @@ const
"PARG": PassArgument,
"RARG": ResetArgs,
"COPY": CopyAtom,
"MOVE": MoveAtom
"MOVE": MoveAtom,
"LOADF": LoadFloat
}.toTable

OpCodeToString* = block:
OpCodeToString* = static:
var vals = initTable[Ops, string]()
for str, operation in OpCodeToTable:
vals[operation] = str

vals

proc toOp*(op: string): Ops {.inline, raises: [ValueError].} =
if op in OpCodeToTable:
return OpCodeToTable[op]
{.push checks: off, inline.}
proc toOp*(op: string): Ops {.raises: [ValueError].} =
when not defined(release):
if op in OpCodeToTable:
return OpCodeToTable[op]
else:
raise newException(
ValueError,
"Invalid operation: " & op
)
else:
raise newException(
ValueError,
"Invalid operation: " & op
)

proc opToString*(op: Ops): string {.inline, raises: [].} =
try:
return OpCodeToString[op]
except KeyError:
assert false, "unreachable"
OpCodeToTable[op]

proc opToString*(op: Ops): string =
OpCodeToString[op]
11 changes: 5 additions & 6 deletions src/mirage/runtime/tokenizer.nim
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import std/[options, strutils, tables, math]
import ./shared
import pretty

type
TokenizerDefect* = object of Defect
Expand Down Expand Up @@ -128,19 +129,17 @@ proc consumeNumeric*(tokenizer: Tokenizer): Token =
(true, 1f)
else:
(false, 1f)

if hasSign:
tokenizer.forwards(1)

var
integralPart: float64
digit: uint32

while unpack(charToDecimalDigit(tokenizer.nextChar()), digit):
while not tokenizer.isEof() and unpack(charToDecimalDigit(tokenizer.nextChar()), digit):
integralPart = integralPart * 10'f64 + digit.float64
tokenizer.forwards(1)
if tokenizer.isEof():
break

var
isInteger = true
Expand All @@ -161,7 +160,7 @@ proc consumeNumeric*(tokenizer: Tokenizer): Token =
break

var value = sign * (integralPart + fractionalPart)
if tokenizer.hasAtleast(1) and tokenizer.nextChar() in ['e', 'E']:
#[if tokenizer.hasAtleast(1) and tokenizer.nextChar() in ['e', 'E']:
if tokenizer.charAt(1) in {'0' .. '9'} or
tokenizer.hasAtleast(2) and tokenizer.charAt(1) in ['+', '-'] and
tokenizer.charAt(2) in {'0' .. '9'}:
Expand All @@ -188,7 +187,7 @@ proc consumeNumeric*(tokenizer: Tokenizer): Token =
if tokenizer.isEof():
break
value *= pow(10'f64, sign * exponent)
value *= pow(10'f64, sign * exponent)]#

let intValue: Option[int32] =
case isInteger
Expand Down
13 changes: 13 additions & 0 deletions tests/tpulsarfloats.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import std/[tables, options]
import mirage/atom
import mirage/runtime/pulsar/interpreter

let i = newPulsarInterpreter("""
CLAUSE main
1 LOADF 0 1.5
2 CALL print 0
END main
""")

analyze i
run i

0 comments on commit ea0999a

Please sign in to comment.