import bin #this is at the end of the script in case any functions from bin #depend on anything here from fibonaccios.exceptions import * from fibonaccios.apploader import get_app import fibonaccios.apploader # apploader hack import time import usb_cdc import os class App: def __init__(self, os, pid, name, wd, *argv): self.os = os self.pid = pid self.name = name self.store = {} self.next_function = 'main' self.run_at = -1 self.wd = wd self.argv = (self,) + argv self.waiting_for = -1 def iterate(self): os.chdir(self.wd) if time.monotonic() >= self.run_at and not self.waiting_for in self.os.apps: getattr(self, f'F_{self.next_function}')() @property def console(self): if self.pid == self.os.controllers[-1]: return self.os.console else: raise NotConsoleController(self.os.controllers[-1]) def transfer_console(self, recipient): if self.pid == self.os.controllers[-1]: self.os.controllers.append(recipient) else: raise NotConsoleController(self.os.controllers[-1]) def chdir(self, wd): os.chdir(wd) self.wd = os.getcwd() def jump(self, function): self.next_function = function def sleep(self, seconds): self.run_at = time.monotonic() + seconds def exec(self, command, *argv): self.os.apps[self.pid] = get_app(command)(self.os, self.pid, command, self.wd, *argv) def launch(self, command, *argv): return self.os.launch(command, self.wd, *argv) def wait(self, pid): self.waiting_for = pid def end_wait(self): self.waiting_for = -1 def on_exit(self): pass def exit(self): del self.os.apps[self.pid] apploader.App = App # apploader hack class OS: def __init__(self): self.apps = {} self.next_new = 0 self.controllers = [0] self.console = usb_cdc.console usb_cdc.console.timeout = 0 self.next_pidi = 0 self.launch('init', '/') def iterate(self): pid = list(self.apps.keys())[self.next_pidi] function = self.apps[pid].iterate function() try: self.apps[pid] # If this succeds, the app did not exit and next_pidi should # be incremented self.next_pidi += 1 except KeyError: # If self.apps[pid] failed, the app exited and next_pidi # should not be incremented pass self.next_pidi = self.next_pidi % len(self.apps) while not self.controllers[-1] in self.apps.keys(): self.controllers.pop() def launch(self, app, wd, *argv): self.apps[self.next_new] = get_app(app)(self, self.next_new, app, wd, *argv) self.next_new += 1 return self.next_new - 1 def kill(self, pid): try: del self.apps[pid] except KeyError: raise(NoSuchProcess(pid)) def run(): os = OS() while True: os.iterate()