added glad generator and a glad runtime
This commit is contained in:
parent
2017f6195e
commit
ac18a84a9c
62 changed files with 32373 additions and 10 deletions
0
tools/glad-0.1.14a0/glad/lang/common/__init__.py
Normal file
0
tools/glad-0.1.14a0/glad/lang/common/__init__.py
Normal file
242
tools/glad-0.1.14a0/glad/lang/common/generator.py
Normal file
242
tools/glad-0.1.14a0/glad/lang/common/generator.py
Normal file
|
@ -0,0 +1,242 @@
|
|||
from collections import defaultdict
|
||||
from datetime import datetime
|
||||
from itertools import chain
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
from glad.lang.common.loader import NullLoader
|
||||
from glad.opener import URLOpener
|
||||
from glad.util import api_name
|
||||
import glad
|
||||
|
||||
|
||||
if sys.version_info >= (3, 0):
|
||||
from urllib.parse import urlencode
|
||||
else:
|
||||
from urllib import urlencode
|
||||
|
||||
|
||||
HEADER_TEMPLATE = '''
|
||||
{apis_named} loader generated by glad {version} on {date}.
|
||||
|
||||
Language/Generator: {language}
|
||||
Specification: {specification}
|
||||
APIs: {apis}
|
||||
Profile: {profile}
|
||||
Extensions:
|
||||
{extensions}
|
||||
Loader: {loader}
|
||||
Local files: {local_files}
|
||||
Omit khrplatform: {omit_khrplatform}
|
||||
|
||||
Commandline:
|
||||
{commandline}
|
||||
Online:
|
||||
{online}
|
||||
'''
|
||||
|
||||
|
||||
class Generator(object):
|
||||
NAME = None
|
||||
NAME_LONG = None
|
||||
URL = 'http://glad.dav1d.de'
|
||||
|
||||
def __init__(self, path, spec, api, extension_names=None, loader=None,
|
||||
opener=None, local_files=False, omit_khrplatform=False,
|
||||
header_template=HEADER_TEMPLATE):
|
||||
self.path = os.path.abspath(path)
|
||||
|
||||
self.spec = spec
|
||||
for a in api:
|
||||
if a not in self.spec.features:
|
||||
raise ValueError(
|
||||
'Unknown API "{0}" for specification "{1}"'
|
||||
.format(a, self.spec.NAME)
|
||||
)
|
||||
self.api = api
|
||||
self.extension_names = extension_names
|
||||
|
||||
self.has_loader = not loader.disabled
|
||||
self.loader = loader
|
||||
if self.loader is None:
|
||||
self.loader = NullLoader
|
||||
|
||||
self.opener = opener
|
||||
if self.opener is None:
|
||||
self.opener = URLOpener.default()
|
||||
|
||||
self.local_files = local_files
|
||||
self.omit_khrplatform = omit_khrplatform
|
||||
|
||||
self._header_template = header_template
|
||||
|
||||
def open(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def close(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def __enter__(self):
|
||||
self.open()
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
self.close()
|
||||
|
||||
def generate(self):
|
||||
features = list()
|
||||
for api, version in self.api.items():
|
||||
features.extend(self.spec.features[api])
|
||||
|
||||
if version is None:
|
||||
version = list(self.spec.features[api].keys())[-1]
|
||||
self.api[api] = version
|
||||
|
||||
if version not in self.spec.features[api]:
|
||||
raise ValueError(
|
||||
'Unknown version "{0}" for specification "{1}"'
|
||||
.format(version, self.spec.NAME)
|
||||
)
|
||||
|
||||
if self.extension_names is None:
|
||||
self.extension_names = list(chain.from_iterable(self.spec.extensions[a]
|
||||
for a in self.api))
|
||||
|
||||
# sort and eliminate duplicates
|
||||
self.extension_names = list(sorted(set(self.extension_names)))
|
||||
|
||||
e = list(chain.from_iterable(self.spec.extensions[a] for a in self.api))
|
||||
for ext in self.extension_names:
|
||||
if ext not in e:
|
||||
raise ValueError(
|
||||
'Invalid extension "{0}" for specification "{1}"'
|
||||
.format(ext, self.spec.NAME)
|
||||
)
|
||||
|
||||
self.generate_header()
|
||||
|
||||
types = [t for t in self.spec.types if t.api is None or t.api in self.api]
|
||||
self.generate_types(types)
|
||||
|
||||
f = list()
|
||||
for api, version in self.api.items():
|
||||
f.extend([value for key, value in self.spec.features[api].items()
|
||||
if key <= version])
|
||||
enums, functions = merge(f)
|
||||
self.generate_features(f)
|
||||
|
||||
extensions = list()
|
||||
for api in self.api:
|
||||
extensions.extend(self.spec.extensions[api][ext]
|
||||
for ext in self.extension_names if ext
|
||||
in self.spec.extensions[api])
|
||||
self.generate_extensions(extensions, enums, functions)
|
||||
|
||||
fs = defaultdict(list)
|
||||
es = defaultdict(list)
|
||||
for api, version in self.api.items():
|
||||
fs[api].extend(
|
||||
[value for key, value in
|
||||
self.spec.features[api].items() if key <= version]
|
||||
)
|
||||
es[api].extend(self.spec.extensions[api][ext]
|
||||
for ext in self.extension_names if ext
|
||||
in self.spec.extensions[api])
|
||||
self.generate_loader(fs, es)
|
||||
|
||||
@property
|
||||
def header(self):
|
||||
apis_named = ', '.join(sorted(set(api_name(api) for api in self.api)))
|
||||
date = datetime.now().strftime('%c')
|
||||
language = self.NAME_LONG
|
||||
specification = self.spec.NAME
|
||||
apis = ', '.join('{}={}'.format(api, '.'.join(map(str, version))) for api, version in self.api.items())
|
||||
profile = getattr(self.spec, 'profile', '-')
|
||||
extensions = ',\n '.join(self.extension_names)
|
||||
online = self.online
|
||||
if len(online) > 2000:
|
||||
online = 'Too many extensions'
|
||||
|
||||
return self._header_template.format(
|
||||
apis_named=apis_named,
|
||||
version=glad.__version__,
|
||||
date=date,
|
||||
language=language,
|
||||
specification=specification,
|
||||
apis=apis,
|
||||
profile=profile,
|
||||
extensions=extensions,
|
||||
loader=self.has_loader,
|
||||
local_files=self.local_files,
|
||||
omit_khrplatform=self.omit_khrplatform,
|
||||
commandline=self.commandline,
|
||||
online=online
|
||||
)
|
||||
|
||||
@property
|
||||
def commandline(self):
|
||||
profile = getattr(self.spec, 'profile', None)
|
||||
if profile is not None:
|
||||
profile = '--profile="{}"'.format(profile)
|
||||
|
||||
api = '--api="{}"'.format(','.join(
|
||||
'{}={}'.format(api, '.'.join(map(str, version))) for api, version in self.api.items())
|
||||
)
|
||||
generator = '--generator="{}"'.format(self.NAME)
|
||||
specification = '--spec="{}"'.format(self.spec.NAME)
|
||||
loader = '' if self.has_loader else '--no-loader'
|
||||
extensions = '--extensions="{}"'.format(','.join(self.extension_names))
|
||||
local_files = '--local-files' if self.local_files else ''
|
||||
omit_khrplatform = '--omit-khrplatform' if self.omit_khrplatform else ''
|
||||
|
||||
return ' '.join(filter(None, [
|
||||
profile, api, generator, specification,
|
||||
loader, local_files, omit_khrplatform, extensions
|
||||
]))
|
||||
|
||||
@property
|
||||
def online(self):
|
||||
profile = getattr(self.spec, 'profile', None)
|
||||
if profile is not None:
|
||||
profile = ('profile', profile)
|
||||
|
||||
api = [('api', s) for s in ('{}={}'.format(api, '.'.join(map(str, version))) for api, version in self.api.items())]
|
||||
generator = ('language', self.NAME)
|
||||
specification = ('specification', self.spec.NAME)
|
||||
loader = ('loader', 'on') if self.has_loader else None
|
||||
extensions = [('extensions', ext) for ext in self.extension_names]
|
||||
|
||||
data = [profile, generator, specification, loader]
|
||||
data.extend(api)
|
||||
data.extend(extensions)
|
||||
data = list(filter(None, data))
|
||||
serialized = urlencode(data)
|
||||
|
||||
# TODO: --local-files, --omit-khrplatform
|
||||
return '{}/#{}'.format(self.URL, serialized)
|
||||
|
||||
def generate_header(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def generate_loader(self, features, extensions):
|
||||
raise NotImplementedError
|
||||
|
||||
def generate_types(self, types):
|
||||
raise NotImplementedError
|
||||
|
||||
def generate_features(self, features):
|
||||
raise NotImplementedError
|
||||
|
||||
def generate_extensions(self, extensions, enums, functions):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def merge(features):
|
||||
enums = set()
|
||||
functions = set()
|
||||
|
||||
for feature in features:
|
||||
enums |= set(feature.enums)
|
||||
functions |= set(feature.functions)
|
||||
|
||||
return enums, functions
|
60
tools/glad-0.1.14a0/glad/lang/common/loader.py
Normal file
60
tools/glad-0.1.14a0/glad/lang/common/loader.py
Normal file
|
@ -0,0 +1,60 @@
|
|||
class BaseLoader(object):
|
||||
def __init__(self, apis, disabled=False, local_files=False):
|
||||
self.apis = apis
|
||||
self.disabled = disabled
|
||||
self.local_files = local_files
|
||||
|
||||
def write(self, fobj):
|
||||
raise NotImplementedError
|
||||
|
||||
def write_begin_load(self, fobj):
|
||||
raise NotImplementedError
|
||||
|
||||
def write_end_load(self, fobj):
|
||||
raise NotImplementedError
|
||||
|
||||
def write_find_core(self, fobj):
|
||||
raise NotImplementedError
|
||||
|
||||
def write_has_ext(self, fobj):
|
||||
raise NotImplementedError
|
||||
|
||||
def write_header(self, fobj):
|
||||
raise NotImplementedError
|
||||
|
||||
def write_header_end(self, fobj):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class NullLoader(BaseLoader):
|
||||
def write_begin_load(self, fobj):
|
||||
pass
|
||||
|
||||
def write_end_load(self, fobj):
|
||||
pass
|
||||
|
||||
def write_header_end(self, fobj):
|
||||
pass
|
||||
|
||||
def write_has_ext(self, fobj):
|
||||
pass
|
||||
|
||||
def write(self, fobj):
|
||||
pass
|
||||
|
||||
def write_header(self, fobj):
|
||||
pass
|
||||
|
||||
def write_find_core(self, fobj):
|
||||
pass
|
||||
|
||||
def __getattr__(self, name):
|
||||
try:
|
||||
return self.__getattribute__(name)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def dummy(*args, **kwargs):
|
||||
pass
|
||||
return dummy
|
||||
|
13
tools/glad-0.1.14a0/glad/lang/common/util.py
Normal file
13
tools/glad-0.1.14a0/glad/lang/common/util.py
Normal file
|
@ -0,0 +1,13 @@
|
|||
import os.path
|
||||
import os
|
||||
|
||||
|
||||
def enforce(exp, message, exc):
|
||||
if not exp:
|
||||
raise exc(message)
|
||||
|
||||
|
||||
def makefiledir(path):
|
||||
dir = os.path.split(path)[0]
|
||||
if not os.path.exists(dir):
|
||||
os.makedirs(dir)
|
Loading…
Add table
Add a link
Reference in a new issue