Skip to content

Commit

Permalink
cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
Nimaoth committed Oct 5, 2024
1 parent 49026ec commit c957a5c
Show file tree
Hide file tree
Showing 25 changed files with 404 additions and 522 deletions.
2 changes: 1 addition & 1 deletion patches/codegen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ proc genCasesCode*(program: Program, sType, uType, uId: NimNode, ms, s, si, sima
push(`ms`.precStack, 0)
`ip` = `ipNext`
else:
let (iPrec, iAssoc) = (i.prec.newLit, i.assoc.newLit)
let (iPrec, _) = (i.prec.newLit, i.assoc.newLit)
let exp = if i.assoc == assocLeft:
quote: peek(`ms`.precStack) < `iPrec`
else:
Expand Down
2 changes: 1 addition & 1 deletion src/app.nim
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,7 @@ proc getEventHandlerConfig*(self: App, context: string): EventHandlerConfig =
nil

self.eventHandlerConfigs[context] = newEventHandlerConfig(context, parentConfig)
assertNoEx self.eventHandlerConfigs[context].setLeaders(self.leaders)
self.eventHandlerConfigs[context].setLeaders(self.leaders)

return self.eventHandlerConfigs[context].catch(EventHandlerConfig())

Expand Down
17 changes: 10 additions & 7 deletions src/input.nim
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import input_api

export input_api

{.push gcsafe.}
{.push raises: [].}

logCategory "input"

type
Expand Down Expand Up @@ -47,10 +50,10 @@ type
MouseButton* {.pure.} = enum
Left, Middle, Right, DoubleClick, TripleClick, Unknown

proc inputToString*(input: int64, modifiers: Modifiers = {}): string {.gcsafe, raises: [].}
proc inputToString*(input: int64, modifiers: Modifiers = {}): string

let capturePattern = re"<(.*?)>"
proc fillCaptures(dfa: CommandDFA, state: CommandState, args: string): string {.gcsafe, raises: [].} =
proc fillCaptures(dfa: CommandDFA, state: CommandState, args: string): string =
# debug &"fillCaptures {args}, {state}"
var last = 0
{.gcsafe.}:
Expand Down Expand Up @@ -85,7 +88,7 @@ proc fillCaptures(dfa: CommandDFA, state: CommandState, args: string): string {.
proc possibleFunctionIndices*(state: CommandState): int =
return state.functionIndices.bitSetCard

proc getAction*(dfa: CommandDFA, state: CommandState): (string, string) {.gcsafe, raises: [].} =
proc getAction*(dfa: CommandDFA, state: CommandState): (string, string) =
if state.functionIndices.bitSetCard != 1:
log(lvlError, fmt"Multiple possible functions found: {state}")

Expand All @@ -107,7 +110,7 @@ proc stepEmpty(dfa: CommandDFA, state: CommandState): seq[CommandState] =

result.incl dfa.stepEmpty(newState)

proc stepInput(dfa: CommandDFA, state: CommandState, currentInput: int64, mods: Modifiers, result: var seq[CommandState]) {.gcsafe.} =
proc stepInput(dfa: CommandDFA, state: CommandState, currentInput: int64, mods: Modifiers, result: var seq[CommandState]) =
for transition in dfa.states[state.current].transitions.pairs:
if currentInput in transition[0]:
if not transition[1].next.contains(mods):
Expand All @@ -123,7 +126,7 @@ proc stepInput(dfa: CommandDFA, state: CommandState, currentInput: int64, mods:
result.add newState
result.add dfa.stepEmpty(newState)

proc stepAll*(dfa: CommandDFA, state: CommandState, currentInput: int64, mods: Modifiers, beginEmpty: bool): seq[CommandState] {.gcsafe.} =
proc stepAll*(dfa: CommandDFA, state: CommandState, currentInput: int64, mods: Modifiers, beginEmpty: bool): seq[CommandState] =
if currentInput == 0:
log(lvlError, "Input 0 is invalid")
return @[]
Expand All @@ -141,7 +144,7 @@ proc stepAll*(dfa: CommandDFA, state: CommandState, currentInput: int64, mods: M

return

proc stepAll*(dfa: CommandDFA, states: seq[CommandState], currentInput: int64, mods: Modifiers): seq[CommandState] {.gcsafe.} =
proc stepAll*(dfa: CommandDFA, states: seq[CommandState], currentInput: int64, mods: Modifiers): seq[CommandState] =
# echo &"stepAll {inputToString(currentInput, mods)}, {states.len}, {states}"
# defer:
# echo &"stepAll -> {result}"
Expand Down Expand Up @@ -471,7 +474,7 @@ proc handleNextInput(

# dfa.fillTransitionFunctionIndicesRec(0, {})

proc buildDFA*(commands: Table[string, Table[string, string]], leaders: seq[string] = @[]): CommandDFA {.gcsafe, raises: [].} =
proc buildDFA*(commands: Table[string, Table[string, string]], leaders: seq[string] = @[]): CommandDFA =
new(result)

# debugf"commands: {commands}"
Expand Down
194 changes: 82 additions & 112 deletions src/misc/connection.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import std/[strutils]
import misc/[util, custom_async, custom_logger]
import misc/[util, custom_async, custom_logger, async_process]

{.push gcsafe.}

logCategory "connections"

Expand All @@ -14,118 +15,87 @@ method send*(connection: Connection, data: string): Future[void] {.base, gcsafe,

{.pop.}

when not defined(js):
import misc/[async_process, custom_asyncnet]
type ConnectionAsyncProcess = ref object of Connection
process: AsyncProcess
type ConnectionAsyncProcess = ref object of Connection
process: AsyncProcess

method close*(connection: ConnectionAsyncProcess) =
try:
connection.process.destroy()
except OSError:
raise newException(IOError, "Failed to destroy process", getCurrentException())

method recvLine*(connection: ConnectionAsyncProcess): Future[string] =
connection.process.recvLine()

method recv*(connection: ConnectionAsyncProcess, length: int): Future[string] =
connection.process.recv(length)

method send*(connection: ConnectionAsyncProcess, data: string): Future[void] =
connection.process.send(data)

proc asyncVoid() {.async.} =
discard

proc newAsyncProcessConnection*(path: string, args: seq[string]):
Future[ConnectionAsyncProcess] {.async.} =

log lvlInfo, fmt"Creating async process connection at {path} {args}"

let process = startAsyncProcess(path, args, autoRestart=false)

var fut = newFuture[void]("newAsyncProcessConnection")
process.onRestarted = proc(): Future[void] =
fut.complete()
return asyncVoid()

await fut
return ConnectionAsyncProcess(process: process)

# todo
# type ConnectionAsyncSocket* = ref object of Connection
# socket: AsyncSocket
# activeRequests: int = 0 # Required because AsyncSocket asserts that we don't close the socket while
# # recvLine is in progress
# closeRequested: bool = false

# method close*(connection: ConnectionAsyncSocket) =
# if connection.activeRequests > 0:
# connection.closeRequested = true
# else:
# connection.socket.close()
# connection.socket = nil

# template handleClose(connection: Connection): untyped =
# inc connection.activeRequests
# defer:
# dec connection.activeRequests
# if connection.closeRequested and connection.activeRequests == 0:
# connection.closeRequested = false
# connection.close()

# method recvLine*(connection: ConnectionAsyncSocket): Future[string] {.async.} =
# if connection.socket.isNil or connection.socket.isClosed:
# return ""

# connection.handleClose()
# return await connection.socket.recvLine()

method close*(connection: ConnectionAsyncProcess) =
try:
connection.process.destroy()
except OSError:
raise newException(IOError, "Failed to destroy process", getCurrentException())

method recvLine*(connection: ConnectionAsyncProcess): Future[string] =
connection.process.recvLine()
# method recv*(connection: ConnectionAsyncSocket, length: int): Future[string] {.async.} =
# if connection.socket.isNil or connection.socket.isClosed:
# return ""

method recv*(connection: ConnectionAsyncProcess, length: int): Future[string] =
connection.process.recv(length)

method send*(connection: ConnectionAsyncProcess, data: string): Future[void] =
connection.process.send(data)

proc asyncVoid() {.async.} =
discard

proc newAsyncProcessConnection*(path: string, args: seq[string]):
Future[ConnectionAsyncProcess] {.async.} =

log lvlInfo, fmt"Creating async process connection at {path} {args}"

let process = startAsyncProcess(path, args, autoRestart=false)

var fut = newFuture[void]("newAsyncProcessConnection")
process.onRestarted = proc(): Future[void] =
fut.complete()
return asyncVoid()

await fut
return ConnectionAsyncProcess(process: process)

# type ConnectionAsyncSocket* = ref object of Connection
# socket: AsyncSocket
# activeRequests: int = 0 # Required because AsyncSocket asserts that we don't close the socket while
# # recvLine is in progress
# closeRequested: bool = false

# method close*(connection: ConnectionAsyncSocket) =
# if connection.activeRequests > 0:
# connection.closeRequested = true
# else:
# connection.socket.close()
# connection.socket = nil

# template handleClose(connection: Connection): untyped =
# inc connection.activeRequests
# defer:
# dec connection.activeRequests
# if connection.closeRequested and connection.activeRequests == 0:
# connection.closeRequested = false
# connection.close()

# method recvLine*(connection: ConnectionAsyncSocket): Future[string] {.async.} =
# if connection.socket.isNil or connection.socket.isClosed:
# return ""

# connection.handleClose()
# return await connection.socket.recvLine()

# method recv*(connection: ConnectionAsyncSocket, length: int): Future[string] {.async.} =
# if connection.socket.isNil or connection.socket.isClosed:
# return ""

# connection.handleClose()
# return await connection.socket.recv(length)

# method send*(connection: ConnectionAsyncSocket, data: string): Future[void] {.async.} =
# if connection.socket.isNil or connection.socket.isClosed:
# return

# connection.handleClose()
# await connection.socket.send(data)

# proc newAsyncSocketConnection*(host: string, port: Port): Future[ConnectionAsyncSocket] {.async.} =
# log lvlInfo, fmt"Creating async socket connection at {host}:{port.int}"
# let socket = newAsyncSocket()
# await socket.connect(host, port)
# return ConnectionAsyncSocket(socket: socket)

# type ConnectionWebsocket* = ref object of Connection
# websocket: WebSocket
# buffer: string
# processId: int

# method close*(connection: ConnectionWebsocket) =
# connection.websocket.close()

# method recvLine*(connection: ConnectionWebsocket): Future[string] {.async.} =
# var newLineIndex = connection.buffer.find("\r\n")
# while newLineIndex == -1:
# let next = connection.websocket.receiveStrPacket().await
# connection.buffer.append next
# newLineIndex = connection.buffer.find("\r\n")

# let line = connection.buffer[0..<newLineIndex]
# connection.buffer = connection.buffer[newLineIndex + 2..^1]
# return line
# connection.handleClose()
# return await connection.socket.recv(length)

# method recv*(connection: ConnectionWebsocket, length: int): Future[string] {.async.} =
# while connection.buffer.len < length:
# connection.buffer.add connection.websocket.receiveStrPacket().await
# method send*(connection: ConnectionAsyncSocket, data: string): Future[void] {.async.} =
# if connection.socket.isNil or connection.socket.isClosed:
# return

# let res = connection.buffer[0..<length]
# connection.buffer = connection.buffer[length..^1]
# return res
# connection.handleClose()
# await connection.socket.send(data)

# method send*(connection: ConnectionWebsocket, data: string): Future[void] =
# connection.websocket.send(data)
# proc newAsyncSocketConnection*(host: string, port: Port): Future[ConnectionAsyncSocket] {.async.} =
# log lvlInfo, fmt"Creating async socket connection at {host}:{port.int}"
# let socket = newAsyncSocket()
# await socket.connect(host, port)
# return ConnectionAsyncSocket(socket: socket)
8 changes: 7 additions & 1 deletion src/misc/custom_async.nim
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ var gAsyncFrameTimer*: Timer
import std/[threadpool]
{.pop.}

# Prevent bs warnings on builtin types (e.g) because `=destroy(bool)` raises `Exception` when using `spawn`
# Prevent bs warnings on builtin types (e.g bool) because `=destroy(bool)` raises `Exception` when using `spawn`
type NoExceptionDestroy* = object
func `=destroy`*(x: NoExceptionDestroy) {.raises: [].} = discard

Expand Down Expand Up @@ -67,6 +67,12 @@ proc doneFuture*(): Future[void] =
except:
assert false

template readFinished*[T: not void](fut: Future[T]): lent T =
try:
fut.read
except:
raiseAssert("Failed to read unfinished future")

template thenIt*[T](f: Future[T], body: untyped): untyped =
when defined(js):
discard f.then(proc(a: T) =
Expand Down
21 changes: 12 additions & 9 deletions src/misc/delayed_task.nim
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import custom_async
when defined(debugDelayedTasks):
import std/strutils

{.push gcsafe.}
{.push raises: [].}

type
DelayedTask* = ref object
restartCounter: int
Expand All @@ -16,10 +19,10 @@ type
when defined(debugDelayedTasks):
creationStackTrace: string

func isActive*(task: DelayedTask): bool {.gcsafe, raises: [].} = task.active
proc reschedule*(task: DelayedTask) {.gcsafe, raises: [].}
func isActive*(task: DelayedTask): bool = task.active
proc reschedule*(task: DelayedTask)

proc tick(task: DelayedTask): Future[void] {.gcsafe, async.} =
proc tick(task: DelayedTask): Future[void] {.async.} =
let restartCounter = task.restartCounter

defer:
Expand Down Expand Up @@ -57,35 +60,35 @@ proc tick(task: DelayedTask): Future[void] {.gcsafe, async.} =
if not task.repeat:
break

proc reschedule*(task: DelayedTask) {.gcsafe, raises: [].} =
proc reschedule*(task: DelayedTask) =
task.nextTick = getTime() + initDuration(milliseconds=task.interval)
if not task.isActive:
asyncSpawn task.tick()

proc schedule*(task: DelayedTask) {.gcsafe, raises: [].} =
proc schedule*(task: DelayedTask) =
if not task.isActive:
task.nextTick = getTime() + initDuration(milliseconds=task.interval)
asyncSpawn task.tick()

proc newDelayedTask*(interval: int, repeat: bool, autoActivate: bool, callback: proc() {.gcsafe, raises: [].}): DelayedTask {.gcsafe, raises: [].} =
proc newDelayedTask*(interval: int, repeat: bool, autoActivate: bool, callback: proc() {.gcsafe, raises: [].}): DelayedTask =
result = DelayedTask(interval: interval.int64, repeat: repeat, callback: callback)
when defined(debugDelayedTasks):
result.creationStackTrace = getStackTrace()
if autoActivate:
result.reschedule()

proc newDelayedTask*(interval: int, repeat: bool, autoActivate: bool, callback: proc(): Future[void] {.gcsafe, async: (raises: []).}): DelayedTask {.gcsafe, raises: [].} =
proc newDelayedTask*(interval: int, repeat: bool, autoActivate: bool, callback: proc(): Future[void] {.gcsafe, async: (raises: []).}): DelayedTask =
result = DelayedTask(interval: interval.int64, repeat: repeat, callbackAsync: callback)
when defined(debugDelayedTasks):
result.creationStackTrace = getStackTrace()
if autoActivate:
result.reschedule()

proc pause*(task: DelayedTask) {.gcsafe, raises: [].} =
proc pause*(task: DelayedTask) =
task.restartCounter.inc
task.active = false

proc deinit*(task: DelayedTask) {.gcsafe, raises: [].} =
proc deinit*(task: DelayedTask) =
task.pause()
task.callback = nil

Expand Down
Loading

0 comments on commit c957a5c

Please sign in to comment.