View
@@ -6,7 +6,7 @@
import re
from asdl import asdl_ as asdl
from asdl.asdl_ import Module, Type, Constructor, Field, Sum, Product, is_simple
from asdl.asdl_ import Module, Type, Constructor, Field, Sum, Product
# Types for describing tokens in an ASDL specification.
@@ -266,45 +266,61 @@ def visitProduct(self, prod, name):
self.visit(f, name)
def _CheckFieldsAndWire(typ, type_lookup):
"""Create back pointers on a _CompoundType."""
for f in typ.fields:
# Will fail if it doesn't exist
_ = type_lookup.ByFieldInstance(f)
def _AppendFields(field_ast_nodes, type_lookup, out):
for field in field_ast_nodes:
#print(field)
runtime_type = type_lookup[field.type]
# _CompoundType instances have this attribute
assert hasattr(typ, 'type_lookup'), typ
typ.type_lookup = type_lookup # wire it for lookup
# TODO: cache these under 'type*' and 'type?'. Don't want duplicates!
if field.seq:
runtime_type = asdl.ArrayType(runtime_type)
if field.opt:
runtime_type = asdl.MaybeType(runtime_type)
def _MakeReflectionObject(module, app_types=None):
"""Walk an ASDL module and return a reflection object.
out.append((field.name, runtime_type))
It lets you look up types by name.
Args:
module: Module node, root of the AST for a schema.
"""
type_lookup = asdl.TypeLookup(module, app_types=app_types)
def _MakeReflection(module, app_types=None):
# Types that fields are declared with: int, id, word_part, etc.
# Fields are NOT declared with Constructor names.
type_lookup = dict(asdl.BUILTIN_TYPES)
if app_types is not None:
type_lookup.update(app_types)
# NOTE: We need two passes. Types can be mutually recurisve. See
# asdl/arith.asdl.
# First pass: collect declared types and make entries for them.
for d in module.dfns:
ast_node = d.value
if isinstance(ast_node, asdl.Product):
type_lookup[d.name] = asdl.CompoundType([])
elif isinstance(ast_node, asdl.Sum):
type_lookup[d.name] = asdl.SumType()
else:
raise AssertionError(ast_node)
# MAKE BACK POINTERS. From the _CompoundType instance to the type_lookup
# instance.
# TODO: Fix this because it makes it hard to serialize reflection metadata!
if 1:
for node in module.dfns:
assert isinstance(node, Type), node
v = node.value
if isinstance(v, Product):
_CheckFieldsAndWire(v, type_lookup)
# Second pass: resolve type declarations in Product and constructor.
for d in module.dfns:
ast_node = d.value
if isinstance(ast_node, asdl.Product):
runtime_type = type_lookup[d.name]
_AppendFields(ast_node.fields, type_lookup, runtime_type.fields)
elif isinstance(v, Sum):
for cons in v.types:
_CheckFieldsAndWire(cons, type_lookup)
elif isinstance(ast_node, asdl.Sum):
for cons in ast_node.types:
fields_out = []
type_lookup[cons.name] = asdl.CompoundType(fields_out)
_AppendFields(cons.fields, type_lookup, fields_out)
else:
raise AssertionError(v)
else:
raise AssertionError(ast_node)
return type_lookup
return asdl.TypeLookup(type_lookup)
def LoadSchema(f, app_types):
@@ -323,5 +339,5 @@ def LoadSchema(f, app_types):
if v.errors:
raise AssertionError('ASDL file is invalid: %s' % v.errors)
type_lookup = _MakeReflectionObject(schema_ast, app_types)
type_lookup = _MakeReflection(schema_ast, app_types)
return schema_ast, type_lookup
View
@@ -10,7 +10,7 @@
import sys
from asdl import asdl_ as asdl
from asdl import front_end
from asdl import visitor
@@ -111,8 +111,10 @@ def main(argv):
schema_path = argv[1]
type_lookup_import = argv[2]
p = front_end.ASDLParser()
with open(schema_path) as input_f:
module = asdl.parse(input_f)
module = p.parse(input_f)
f = sys.stdout
View
@@ -79,18 +79,27 @@ def _CheckType(value, expected_desc):
except AttributeError:
return False # it's not of the right type
if isinstance(expected_desc, asdl.Product):
return actual_desc is expected_desc
if isinstance(expected_desc, asdl.Sum):
if asdl.is_simple(expected_desc):
if 1:
# !!! INCORRECT STUB IMPLEMENTATION !!!
# TODO: This got broken by the move to compiled reflection data.
# We're only checking types in unit tests right now anyway.
if isinstance(expected_desc, asdl.SumType):
return True
if isinstance(expected_desc, asdl.CompoundType):
return True
else:
if isinstance(expected_desc, asdl.CompoundType):
return actual_desc is expected_desc
else:
for cons in expected_desc.types: # It has to be one of the alternatives
#log("CHECKING desc %s against %s" % (desc, cons))
if actual_desc is cons:
return True
return False
if isinstance(expected_desc, asdl.SumType):
if asdl.is_simple(expected_desc):
return actual_desc is expected_desc
else:
for cons in expected_desc.types: # It has to be one of the alternatives
#log("CHECKING desc %s against %s" % (desc, cons))
if actual_desc is cons:
return True
return False
raise AssertionError(
'Invalid descriptor %r: %r' % (expected_desc.__class__, expected_desc))
@@ -251,7 +260,7 @@ def MakeTypes(module, root, type_lookup):
# change. I haven't run into this problem in practice yet.
class_name = defn.name + '_e'
class_attr = {'ASDL_TYPE': sum_type} # asdl.Sum
class_attr = {'ASDL_TYPE': type_lookup.ByTypeName(defn.name)}
cls = type(class_name, (SimpleObj, ), class_attr)
setattr(root, class_name, cls)
@@ -279,7 +288,7 @@ def MakeTypes(module, root, type_lookup):
tag_num[cons.name] = tag # for enum
class_attr = {
'ASDL_TYPE': cons, # asdl.Constructor
'ASDL_TYPE': type_lookup.ByTypeName(cons.name),
'tag': tag, # Does this API change?
}
@@ -292,7 +301,7 @@ def MakeTypes(module, root, type_lookup):
setattr(root, enum_name, tag_enum)
elif isinstance(typ, asdl.Product):
class_attr = {'ASDL_TYPE': typ}
class_attr = {'ASDL_TYPE': type_lookup.ByTypeName(defn.name)}
cls = type(defn.name, (DebugCompoundObj, ), class_attr)
setattr(root, defn.name, cls)