2022-01-20 21:54:11 +01:00
|
|
|
import strformat
|
|
|
|
|
|
|
|
type
|
2022-01-27 05:37:10 +01:00
|
|
|
NdType* = enum
|
|
|
|
ndNil, ndBool, ndFloat, ndString,
|
|
|
|
ndFunct,
|
2022-01-20 21:54:11 +01:00
|
|
|
|
|
|
|
type
|
2022-01-27 05:37:10 +01:00
|
|
|
NdValue* = object
|
|
|
|
case ndType*: NdType:
|
|
|
|
of ndNil:
|
2022-01-20 21:54:11 +01:00
|
|
|
discard
|
2022-01-27 05:37:10 +01:00
|
|
|
of ndBool:
|
2022-01-20 21:54:11 +01:00
|
|
|
boolValue*: bool
|
2022-01-27 05:37:10 +01:00
|
|
|
of ndFloat:
|
2022-01-20 21:54:11 +01:00
|
|
|
floatValue*: float64
|
2022-01-27 05:37:10 +01:00
|
|
|
of ndString:
|
2022-01-20 21:54:11 +01:00
|
|
|
stringValue*: string
|
2022-01-27 05:37:10 +01:00
|
|
|
of ndFunct:
|
2022-01-27 05:56:09 +01:00
|
|
|
placeholder*: string
|
2022-01-21 00:18:58 +01:00
|
|
|
entryII*: int # entry instruction index
|
2022-01-27 02:03:23 +01:00
|
|
|
|
|
|
|
NatReturn* = object
|
|
|
|
ok*: bool
|
|
|
|
msg*: string
|
2022-01-20 21:54:11 +01:00
|
|
|
|
|
|
|
# KON VALUE HELPERS, MUST BE DEFINED FOR EVERY KONVALUE
|
|
|
|
|
2022-01-27 05:37:10 +01:00
|
|
|
proc `$`*(val: NdValue): string =
|
|
|
|
case val.ndType:
|
|
|
|
of ndFloat:
|
2022-01-20 21:54:11 +01:00
|
|
|
return $val.floatValue
|
2022-01-27 05:37:10 +01:00
|
|
|
of ndBool:
|
2022-01-20 21:54:11 +01:00
|
|
|
return $val.boolValue
|
2022-01-27 05:37:10 +01:00
|
|
|
of ndNil:
|
2022-01-20 21:54:11 +01:00
|
|
|
return "nil"
|
2022-01-27 05:37:10 +01:00
|
|
|
of ndString:
|
2022-01-20 21:54:11 +01:00
|
|
|
return val.stringValue
|
2022-01-27 05:37:10 +01:00
|
|
|
of ndFunct:
|
2022-01-22 17:28:53 +01:00
|
|
|
return &"Function object: {val.entryII}"
|
2022-01-20 21:54:11 +01:00
|
|
|
|
2022-01-27 05:37:10 +01:00
|
|
|
proc isFalsey*(val: NdValue): bool =
|
|
|
|
val.ndType in {ndNil} or (val.ndType == ndBool and not val.boolValue)
|
2022-01-20 21:54:11 +01:00
|
|
|
|
2022-01-27 05:37:10 +01:00
|
|
|
template isTruthy*(val: NdValue): bool =
|
2022-01-20 21:54:11 +01:00
|
|
|
not isFalsey(val)
|
|
|
|
|
2022-01-27 05:37:10 +01:00
|
|
|
proc equal*(val, right: NdValue): bool =
|
|
|
|
if val.ndType != right.ndType:
|
2022-01-20 21:54:11 +01:00
|
|
|
false
|
|
|
|
else:
|
2022-01-27 05:37:10 +01:00
|
|
|
case val.ndType:
|
|
|
|
of ndFloat:
|
2022-01-20 21:54:11 +01:00
|
|
|
val.floatValue == right.floatValue
|
2022-01-27 05:37:10 +01:00
|
|
|
of ndBool:
|
2022-01-20 21:54:11 +01:00
|
|
|
val.boolValue == right.boolValue
|
2022-01-27 05:37:10 +01:00
|
|
|
of ndNil:
|
2022-01-20 21:54:11 +01:00
|
|
|
true
|
2022-01-27 05:37:10 +01:00
|
|
|
of ndString:
|
2022-01-20 21:54:11 +01:00
|
|
|
val.stringValue == right.stringValue
|
2022-01-27 05:37:10 +01:00
|
|
|
of ndFunct:
|
2022-01-22 17:28:53 +01:00
|
|
|
val.entryII == right.entryII
|
2022-01-20 21:54:11 +01:00
|
|
|
|
|
|
|
# NIM VALUE TO KON VALUE WRAPPERS
|
|
|
|
|
2022-01-27 05:37:10 +01:00
|
|
|
proc toNdValue*(val: float): NdValue =
|
|
|
|
NdValue(ndType: ndFloat, floatValue: val)
|
2022-01-20 21:54:11 +01:00
|
|
|
|
2022-01-27 05:37:10 +01:00
|
|
|
proc toNdValue*(val: bool): NdValue =
|
|
|
|
NdValue(ndType: ndBool, boolValue: val)
|
2022-01-20 21:54:11 +01:00
|
|
|
|
2022-01-27 05:37:10 +01:00
|
|
|
proc toNdValue*(val: string): NdValue =
|
|
|
|
NdValue(ndType: ndString, stringValue: val)
|
2022-01-20 21:54:11 +01:00
|
|
|
|
2022-01-27 05:56:09 +01:00
|
|
|
proc newNdFunction*(ii: int): NdValue =
|
|
|
|
NdValue(ndType: ndFunct, entryII: ii)
|
2022-01-21 01:51:55 +01:00
|
|
|
|
2022-01-27 05:37:10 +01:00
|
|
|
proc toNdValue*: NdValue =
|
|
|
|
NdValue(ndType: ndNil)
|
2022-01-20 21:54:11 +01:00
|
|
|
|
2022-01-27 02:03:23 +01:00
|
|
|
# NatReturn misc
|
|
|
|
|
|
|
|
proc natError*(msg: string): NatReturn {.inline.} =
|
|
|
|
NatReturn(ok: false, msg: msg)
|
|
|
|
|
|
|
|
const natOk* = NatReturn(ok: true)
|
2022-01-20 21:54:11 +01:00
|
|
|
|
|
|
|
# OPERATIONS
|
|
|
|
# NOTE: these operations can return ktTypeError with a message if types are invalid
|
|
|
|
|
2022-01-27 05:37:10 +01:00
|
|
|
proc negate*(val: var NdValue): NatReturn {.inline.} =
|
|
|
|
if (val.ndType != ndFloat):
|
2022-01-27 02:03:23 +01:00
|
|
|
return natError("Operand must be a number.")
|
2022-01-20 21:54:11 +01:00
|
|
|
else:
|
2022-01-27 02:03:23 +01:00
|
|
|
val.floatValue = -val.floatValue
|
|
|
|
return natOk
|
2022-01-20 21:54:11 +01:00
|
|
|
|
2022-01-27 05:37:10 +01:00
|
|
|
proc add*(val: var NdValue, right: NdValue): NatReturn {.inline.} =
|
|
|
|
if val.ndType == ndFloat and right.ndType == ndFloat:
|
2022-01-27 02:03:23 +01:00
|
|
|
val.floatValue += right.floatValue
|
2022-01-27 05:37:10 +01:00
|
|
|
elif val.ndType == ndString and right.ndType == ndString:
|
2022-01-27 02:03:23 +01:00
|
|
|
val.stringValue &= right.stringValue
|
2022-01-20 21:54:11 +01:00
|
|
|
else:
|
2022-01-27 05:37:10 +01:00
|
|
|
return natError(&"Attempt to add types {val.ndType} and {right.ndType}.")
|
2022-01-27 02:03:23 +01:00
|
|
|
return natOk
|
|
|
|
|
2022-01-27 05:37:10 +01:00
|
|
|
proc subtract*(val: var NdValue, right: NdValue): NatReturn {.inline.} =
|
|
|
|
if val.ndType == ndFloat and right.ndType == ndFloat:
|
2022-01-27 02:03:23 +01:00
|
|
|
val.floatValue -= right.floatValue
|
2022-01-20 21:54:11 +01:00
|
|
|
else:
|
2022-01-27 05:37:10 +01:00
|
|
|
return natError(&"Attempt to subtract types {val.ndType} and {right.ndType}.")
|
2022-01-27 02:03:23 +01:00
|
|
|
return natOk
|
2022-01-20 21:54:11 +01:00
|
|
|
|
2022-01-27 05:37:10 +01:00
|
|
|
proc multiply*(val: var NdValue, right: NdValue): NatReturn {.inline.} =
|
|
|
|
if val.ndType == ndFloat and right.ndType == ndFloat:
|
2022-01-27 02:03:23 +01:00
|
|
|
val.floatValue *= right.floatValue
|
2022-01-20 21:54:11 +01:00
|
|
|
else:
|
2022-01-27 05:37:10 +01:00
|
|
|
return natError(&"Attempt to multiply types {val.ndType} and {right.ndType}.")
|
2022-01-27 02:03:23 +01:00
|
|
|
return natOk
|
2022-01-20 21:54:11 +01:00
|
|
|
|
2022-01-27 05:37:10 +01:00
|
|
|
proc divide*(val: var NdValue, right: NdValue): NatReturn {.inline.} =
|
|
|
|
if val.ndType == ndFloat and right.ndType == ndFloat:
|
2022-01-27 02:03:23 +01:00
|
|
|
val.floatValue /= right.floatValue
|
2022-01-20 21:54:11 +01:00
|
|
|
else:
|
2022-01-27 05:37:10 +01:00
|
|
|
return natError(&"Attempt to divide types {val.ndType} and {right.ndType}.")
|
2022-01-27 02:03:23 +01:00
|
|
|
return natOk
|
2022-01-20 21:54:11 +01:00
|
|
|
|
2022-01-27 06:09:04 +01:00
|
|
|
proc less*(val: var NdValue, right: NdValue): NatReturn {.inline.} =
|
2022-01-27 05:37:10 +01:00
|
|
|
if val.ndType == ndFloat and right.ndType == ndFloat:
|
2022-01-27 06:09:04 +01:00
|
|
|
val = toNdValue(val.floatValue < right.floatValue)
|
2022-01-20 21:54:11 +01:00
|
|
|
else:
|
2022-01-27 06:09:04 +01:00
|
|
|
return natError(&"Attempt to compare types {val.ndType} and {right.ndType}.")
|
|
|
|
return natOk
|
2022-01-20 21:54:11 +01:00
|
|
|
|
2022-01-27 06:09:04 +01:00
|
|
|
proc greater*(val: var NdValue, right: NdValue): NatReturn {.inline.} =
|
2022-01-27 05:37:10 +01:00
|
|
|
if val.ndType == ndFloat and right.ndType == ndFloat:
|
2022-01-27 06:09:04 +01:00
|
|
|
val = toNdValue(val.floatValue > right.floatValue)
|
2022-01-20 21:54:11 +01:00
|
|
|
else:
|
2022-01-27 06:09:04 +01:00
|
|
|
return natError(&"Attempt to compare types {val.ndType} and {right.ndType}.")
|
|
|
|
return natOk
|