From b65590c35ca16b2293460022b302b396245fe4cd Mon Sep 17 00:00:00 2001 From: xTrayambak Date: Sun, 21 Jul 2024 09:41:22 +0530 Subject: [PATCH 1/3] (add) atom: add support for floats, optimize toStr --- src/mirage/atom.nim | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/src/mirage/atom.nim b/src/mirage/atom.nim index eb404aa..903c3b0 100644 --- a/src/mirage/atom.nim +++ b/src/mirage/atom.nim @@ -17,6 +17,7 @@ type UnsignedInt = 5 Boolean = 6 Object = 7 + Float = 8 AtomOverflowError* = object of CatchableError SequenceError* = object of CatchableError @@ -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] @@ -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 @@ -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 @@ -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) @@ -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( @@ -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: @[] ) @@ -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 = "\n" @@ -291,6 +310,10 @@ proc toString*(atom: MAtom): MAtom {.inline.} = msg &= "" return msg.str() + of Float: + return str( + $atom.floatVal + ) of Null: return str "Null" @@ -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 From 4e9d789987c1facdb40fc582cc625b69fbb06857 Mon Sep 17 00:00:00 2001 From: xTrayambak Date: Sun, 21 Jul 2024 09:41:40 +0530 Subject: [PATCH 2/3] (feat) interpreter: float support --- .../runtime/pulsar/bytecodeopsetconv.nim | 2 +- src/mirage/runtime/pulsar/interpreter.nim | 13 +++++++ src/mirage/runtime/pulsar/operation.nim | 3 ++ src/mirage/runtime/shared.nim | 35 +++++++++++-------- src/mirage/runtime/tokenizer.nim | 11 +++--- tests/tpulsarfloats.nim | 13 +++++++ 6 files changed, 55 insertions(+), 22 deletions(-) create mode 100644 tests/tpulsarfloats.nim diff --git a/src/mirage/runtime/pulsar/bytecodeopsetconv.nim b/src/mirage/runtime/pulsar/bytecodeopsetconv.nim index 728a96a..0130ce1 100644 --- a/src/mirage/runtime/pulsar/bytecodeopsetconv.nim +++ b/src/mirage/runtime/pulsar/bytecodeopsetconv.nim @@ -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 diff --git a/src/mirage/runtime/pulsar/interpreter.nim b/src/mirage/runtime/pulsar/interpreter.nim index f91112e..1fe70d9 100644 --- a/src/mirage/runtime/pulsar/interpreter.nim +++ b/src/mirage/runtime/pulsar/interpreter.nim @@ -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 @@ -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 diff --git a/src/mirage/runtime/pulsar/operation.nim b/src/mirage/runtime/pulsar/operation.nim index d0cbb33..a99a0b5 100644 --- a/src/mirage/runtime/pulsar/operation.nim +++ b/src/mirage/runtime/pulsar/operation.nim @@ -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: @@ -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 diff --git a/src/mirage/runtime/shared.nim b/src/mirage/runtime/shared.nim index f665972..6d602ad 100644 --- a/src/mirage/runtime/shared.nim +++ b/src/mirage/runtime/shared.nim @@ -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, @@ -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] diff --git a/src/mirage/runtime/tokenizer.nim b/src/mirage/runtime/tokenizer.nim index 76d4171..3b6cbbb 100644 --- a/src/mirage/runtime/tokenizer.nim +++ b/src/mirage/runtime/tokenizer.nim @@ -5,6 +5,7 @@ import std/[options, strutils, tables, math] import ./shared +import pretty type TokenizerDefect* = object of Defect @@ -128,7 +129,7 @@ proc consumeNumeric*(tokenizer: Tokenizer): Token = (true, 1f) else: (false, 1f) - + if hasSign: tokenizer.forwards(1) @@ -136,11 +137,9 @@ proc consumeNumeric*(tokenizer: Tokenizer): Token = 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 @@ -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'}: @@ -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 diff --git a/tests/tpulsarfloats.nim b/tests/tpulsarfloats.nim new file mode 100644 index 0000000..749870f --- /dev/null +++ b/tests/tpulsarfloats.nim @@ -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 From ebc375776f96ddf4fc7db36b45127e001064b9a8 Mon Sep 17 00:00:00 2001 From: xTrayambak Date: Sun, 21 Jul 2024 09:42:55 +0530 Subject: [PATCH 3/3] (bump) 0.1.6 -> 0.1.7 --- mirage.nimble | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mirage.nimble b/mirage.nimble index be0f208..fc6bf46 100644 --- a/mirage.nimble +++ b/mirage.nimble @@ -1,6 +1,6 @@ # Package -version = "0.1.6" +version = "0.1.7" author = "xTrayambak" description = "A nifty bytecode generator and runtime" license = "MIT"