Skip to content
This repository has been archived by the owner on Sep 21, 2021. It is now read-only.

Implement code generator #9

Closed
wants to merge 31 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
e8b7235
Implement code generator
roblabla Jan 12, 2018
9f394ee
Handle refcounted construction and destruction properly
roblabla Jan 15, 2018
166213e
Hide dependency on sm, use goto for err handling
roblabla Jan 18, 2018
5667dc7
Properly decrement refcount on init failure
roblabla Jan 19, 2018
a326031
Document struct fields
roblabla Jan 17, 2018
6cbf6a4
Add usb:ds documentation
roblabla Jan 17, 2018
58bff8c
Add interface-level comments
roblabla Jan 17, 2018
76584c9
Fix silly mistakes
roblabla Jan 17, 2018
204ba97
Add command version range in the AST
roblabla Jan 17, 2018
c94537d
Add KObject specification
roblabla Jan 17, 2018
66dab4a
Generate docs
roblabla Jan 17, 2018
fbf5d05
Implement decorator syntax proposed by hthh
roblabla Jan 18, 2018
cbdc4aa
Show the version number in docs, fix a small bug, and document versio…
roblabla Jan 18, 2018
26e2e57
Run gendocs
roblabla Jan 18, 2018
21f828b
Add a switchbrew scraper
roblabla Jan 19, 2018
128cd99
Grab interface name from switchbrew
roblabla Jan 22, 2018
0f49d4e
Add a script to fuse auto.id and switchbrew data
roblabla Jan 22, 2018
4926013
Now with 100% more sorting, 200% more interfaces, and 300% more fusing
roblabla Jan 23, 2018
205f169
Remove PM, as switchbrew has more info
roblabla Jan 26, 2018
2932e23
Fix the links
roblabla Jan 26, 2018
41713ab
Rerun gendocs
roblabla Jan 26, 2018
67e6808
Namespace types, replace void with unknown
roblabla Feb 19, 2018
80ffc28
Rename destructor to %s_destruct
roblabla Feb 19, 2018
51f26bc
Various improvements
roblabla Feb 19, 2018
33e4f0b
Python3 compatibility
roblabla Feb 20, 2018
23440bc
Python3 compat, use argparse instead of getopt
roblabla Feb 20, 2018
cd058c9
Fix fsp-srv definition
roblabla Feb 21, 2018
5ecd021
Fix a bunch of bugs. Start generating the header
roblabla Feb 21, 2018
aaabbf0
Merge branch 'feature-betterIPC' into feature-codegen
roblabla Feb 21, 2018
2a491f7
Port gencode to new version
roblabla Feb 21, 2018
d28ee46
Document undocumented functions
roblabla Mar 18, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
*.pyc
ipcdefs/cache
*.cache
node_modules/
4,455 changes: 2,725 additions & 1,730 deletions docs/ifaces.html

Large diffs are not rendered by default.

311 changes: 171 additions & 140 deletions docs/index.html

Large diffs are not rendered by default.

884 changes: 666 additions & 218 deletions docs/types.html

Large diffs are not rendered by default.

64 changes: 50 additions & 14 deletions idparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,32 @@
sname = /[a-zA-Z_][a-zA-Z0-9_:\-]*/ ;
serviceNameList = @:','.{ sname } ;
template = '<' @:','.{ expression } '>' ;
structField = type [ name ] ';' ;
structField = doc:{ comment }* type:type name:name ';' ;
type =
| 'struct' '{' structFields:{ structField }+ '}'
| 'struct' [ template ] '{' structFields:{ structField }+ '}'
| name:name template:[ template ]
;

typeDef = 'type' name:name '=' type:type ';' ;
typeDef = doc:{ comment }* 'type' name:name '=' type:type ';' ;

interface = 'interface' name:name [ 'is' serviceNames:serviceNameList ] '{' functions:{ funcDef }* '}' ;
interface = doc:{ comment }* 'interface' name:name [ 'is' serviceNames:serviceNameList ] '{' functions:{ funcDef }* '}' ;
namedTuple = '(' @:','.{ type [ name ] } ')' ;
namedType = type [ name ] ;
comment = '#' line:/[^\\n]*/;
funcDef = doc:{ comment }* '[' cmdId:number ']' name:name inputs:namedTuple [ '->' outputs:( namedType | namedTuple ) ] ';' ;
range = [start:(number '.' number '.' number)] '-' [end:(number '.' number '.' number)] ;
decorator = '@' @:decoratorType ;
versionNumber = number '.' number '.' number ;
decoratorType
=
| type:'version' '(' startVersion:versionNumber postfix:[('+' | '-' endVersion:versionNumber)] ')'
| type:'undocumented'
;

funcDef = doc:{ comment }* decorators:{ decorator }* '[' cmdId:number ']' name:name inputs:namedTuple [ '->' outputs:( namedType | namedTuple ) ] ';' ;
'''

versionInfo = [ '1.0.0', '2.0.0', '2.1.0', '2.2.0', '2.3.0', '3.0.0', '3.0.1', '3.0.2', '4.0.0', '4.0.1', '4.1.0' ]

class Semantics(object):
def number(self, ast):
if ast.startswith('0x'):
Expand All @@ -59,9 +70,9 @@ def parseType(type):
assert(not(type['template'] is not None and type['structFields'] is not None))
name, template, structFields = type['name'], type['template'], type['structFields']
if template is not None:
return [name] + map(parseType, template)
return [name] + list(map(parseType, template))
elif structFields is not None:
return ["struct"] + map(lambda x: [x[1], parseType(x[0])], structFields)
return ["struct"] + [list(map(lambda x: [x['name'], parseType(x['type']), list(map(lambda x: x.line, x['doc']))], structFields))]
else:
return [name]

Expand All @@ -81,18 +92,41 @@ def parse(data):
if 'functions' not in elem:
continue
#assert elem['name'] not in ifaces
ifaces[elem['name']] = iface = {}
ifaces[elem['name']] = iface = { "doc": "", "cmds": []}
if elem['serviceNames']:
services[elem['name']] = list(elem['serviceNames'])

iface['doc'] = "\n".join(map(lambda x: x.line, elem['doc']))
for func in elem['functions']:
if func['name'] in iface:
print >>sys.stderr, 'Duplicate function %s in %s' % (func['name'], elem['name'])
sys.exit(1)

assert func['name'] not in iface
iface[func['name']] = fdef = {}
fdef = {}
iface['cmds'].append(fdef)
fdef['name'] = func['name']
fdef['cmdId'] = func['cmdId']
fdef['undocumented'] = False

# Handle decorators
for decorator in func['decorators']:
if decorator['type'] == 'undocumented':
fdef['undocumented'] = True
elif decorator['type'] == 'version':
fdef['versionAdded'] = "".join(map(str, decorator['startVersion']))
if decorator['postfix'] is None:
fdef['lastVersion'] = fdef['versionAdded']
elif decorator['postfix'] == '+':
fdef['versionRemoved'] = None
else:
fdef['lastVersion'] = "".join(map(str, decorator['endVersion']))

# Set default values for "missing" decorators
if 'versionAdded' not in fdef:
fdef['versionAdded'] = "1.0.0"
if 'lastVersion' not in fdef:
fdef['lastVersion'] = None

fdef['doc'] = "\n".join(map(lambda x: x.line, func['doc']))
fdef['inputs'] = [(name, parseType(type)) for type, name in func['inputs']]
if func['outputs'] is None:
Expand All @@ -106,12 +140,14 @@ def parse(data):

def getAll():
dir = os.path.dirname(os.path.realpath(__file__)) + '/'
fns = [dir + 'ipcdefs/auto.id'] + [x for x in glob.glob(dir + 'ipcdefs/*.id') if x != dir + 'ipcdefs/auto.id']
fns = [dir + 'ipcdefs/auto.id', dir + 'ipcdefs/switchbrew.id'] + [x for x in glob.glob(dir + 'ipcdefs/*.id') if x != dir + 'ipcdefs/auto.id' and x != dir + 'ipcdefs/switchbrew.id']

if os.path.exists(dir + 'ipcdefs/cache') and all(os.path.getmtime(dir + 'ipcdefs/cache') > os.path.getmtime(x) for x in fns):
res = json.load(file(dir + 'ipcdefs/cache'))
res = json.load(open(dir + 'ipcdefs/cache'))
else:
res = parse('\n'.join(file(fn).read() for fn in fns))
with file(dir + 'ipcdefs/cache', 'w') as fp:
res = parse('\n'.join(open(fn).read() for fn in fns))
with open(dir + 'ipcdefs/cache', 'w') as fp:
json.dump(res, fp)
# TODO: Check coherence. Especially of cmdId/version range (For each
# cmd ID, we need to make sure there is no version overlap !)
return res
Loading