import Scanner.Protocol import Scanner.Parser import Scanner.Processor import Scanner.Generator open WaylandScanner def parseRawProtocol (path : System.FilePath) : IO Raw.ProtocolDesc := do parse (← IO.FS.readFile path) |>.mapError (fun ε ↦ s!"{path}: {ε}") |> IO.ofExcept def writeProtocol (protocol : Client.ProtocolDesc) (rootModule : String) (rootModulePath : System.FilePath) : IO Unit := do let protocolPath := rootModulePath / protocol.name.pascalCase IO.FS.createDirAll protocolPath let umbrellaPath := protocolPath.addExtension "lean" IO.FS.writeFile umbrellaPath <| generateUmbrella rootModule protocol let headerPath := protocolPath / "Header.lean" IO.FS.writeFile headerPath <| generateHeader rootModule protocol let interfacePath := protocolPath / "Interface.lean" IO.FS.writeFile interfacePath <| generateInterface rootModule protocol let resolvedPath := protocolPath / "Resolved.lean" IO.FS.writeFile resolvedPath <| generateResolved rootModule protocol let requestsPath := protocolPath / "Requests.lean" IO.FS.writeFile requestsPath <| generateRequests rootModule protocol def writeIndex (protocols : Array Client.ProtocolDesc) (rootModule : String) (rootModulePath : System.FilePath) : IO Unit := do let indexPath := rootModulePath.addExtension "lean" IO.FS.writeFile indexPath <| generateIndex rootModule protocols def process (rootModule : String) (outPath : System.FilePath) (srcPath : System.FilePath) : IO UInt32 := do let rawProtocols ← (← srcPath.readDir) |>.map IO.FS.DirEntry.path |>.mapM parseRawProtocol let clientProtocols ← processProtocols rawProtocols |> IO.ofExcept let rootModuleComponents := rootModule.split "." |>.map String.Slice.toString |>.toArray let rootModulePath := rootModuleComponents.foldl (· / ·) outPath IO.FS.createDirAll rootModulePath for protocol in clientProtocols do writeProtocol protocol rootModule rootModulePath writeIndex clientProtocols rootModule rootModulePath return 0 def usage : IO UInt32 := do IO.println "Usage:" IO.println " lake exe WaylandScanner -- " IO.println "" IO.println "Description:" IO.println " Read all (XML) protocols from the directory and" IO.println " generate bindings in the namespace, where the" IO.println " root source path is located at ." return 1 def main (args : List String) : IO UInt32 := match args with | [rootModule, outPath, srcPath] => process rootModule outPath srcPath | _ => usage