Commit 2dac17d8 by Logan Weber Committed by Jared Roesch

[Relay] Move prelude to text format (#3939)

* Fix parser

* Doc fix

* Add module utility functions necessary for prelude

* Implement prelude in text format

* Remove programmatically constructed prelude defs

* Fix 0-arity type conses in pretty printer and test

* Make prelude loading backwards-compatible

* Fix patterns

* Improve some prelude defs

* Fix `ImportFromStd`

It needs to also follow the "add unchecked, add checked" pattern

* Lint roller

* Woops

* Address feedback

* Fix `test_list_constructor` VM test

* Fix `test_adt.py` failures
parent 9b46ace1
...@@ -92,7 +92,7 @@ class Var; ...@@ -92,7 +92,7 @@ class Var;
/*! /*!
* \brief A variable node in the IR. * \brief A variable node in the IR.
* *
* A vraible is uniquely identified by its address. * A variable is uniquely identified by its address.
* *
* Each variable is only binded once in the following nodes: * Each variable is only binded once in the following nodes:
* - Allocate * - Allocate
......
...@@ -117,7 +117,8 @@ class ExprFunctor<R(const Expr& n, Args...)> { ...@@ -117,7 +117,8 @@ class ExprFunctor<R(const Expr& n, Args...)> {
virtual R VisitExpr_(const ConstructorNode* op, Args... args) EXPR_FUNCTOR_DEFAULT; virtual R VisitExpr_(const ConstructorNode* op, Args... args) EXPR_FUNCTOR_DEFAULT;
virtual R VisitExpr_(const MatchNode* op, Args... args) EXPR_FUNCTOR_DEFAULT; virtual R VisitExpr_(const MatchNode* op, Args... args) EXPR_FUNCTOR_DEFAULT;
virtual R VisitExprDefault_(const Node* op, Args...) { virtual R VisitExprDefault_(const Node* op, Args...) {
throw Error(std::string("Do not have a default for ") + op->type_key()); LOG(FATAL) << "Do not have a default for " << op->type_key();
throw;
} }
private: private:
......
...@@ -88,20 +88,33 @@ class ModuleNode : public RelayNode { ...@@ -88,20 +88,33 @@ class ModuleNode : public RelayNode {
TVM_DLL void Add(const GlobalVar& var, const Function& func, bool update = false); TVM_DLL void Add(const GlobalVar& var, const Function& func, bool update = false);
/*! /*!
* \brief Add a function to the global environment.
* \param var The name of the global function.
* \param func The function.
*
* It does not do type inference as Add does.
*/
TVM_DLL void AddUnchecked(const GlobalVar& var, const Function& func);
/*!
* \brief Add a type-level definition to the global environment. * \brief Add a type-level definition to the global environment.
* \param var The var of the global type definition. * \param var The var of the global type definition.
* \param type The type definition. * \param type The ADT.
* \param update Controls whether you can replace a definition in the
* environment.
*/ */
TVM_DLL void AddDef(const GlobalTypeVar& var, const TypeData& type); TVM_DLL void AddDef(const GlobalTypeVar& var, const TypeData& type, bool update = false);
/*! /*!
* \brief Add a function to the global environment. * \brief Add a type definition to the global environment.
* \param var The name of the global function. * \param var The name of the global function.
* \param func The function. * \param type The ADT.
* \param update Controls whether you can replace a definition in the
* environment.
* *
* It does not do type inference as Add does. * It does not do type inference as AddDef does.
*/ */
TVM_DLL void AddUnchecked(const GlobalVar& var, const Function& func); TVM_DLL void AddDefUnchecked(const GlobalTypeVar& var, const TypeData& type, bool update = false);
/*! /*!
* \brief Update a function in the global environment. * \brief Update a function in the global environment.
...@@ -111,6 +124,13 @@ class ModuleNode : public RelayNode { ...@@ -111,6 +124,13 @@ class ModuleNode : public RelayNode {
TVM_DLL void Update(const GlobalVar& var, const Function& func); TVM_DLL void Update(const GlobalVar& var, const Function& func);
/*! /*!
* \brief Update a type definition in the global environment.
* \param var The name of the global type definition to update.
* \param type The new ADT.
*/
TVM_DLL void UpdateDef(const GlobalTypeVar& var, const TypeData& type);
/*!
* \brief Remove a function from the global environment. * \brief Remove a function from the global environment.
* \param var The name of the global function to update. * \param var The name of the global function to update.
*/ */
...@@ -131,6 +151,12 @@ class ModuleNode : public RelayNode { ...@@ -131,6 +151,12 @@ class ModuleNode : public RelayNode {
TVM_DLL GlobalVar GetGlobalVar(const std::string& str) const; TVM_DLL GlobalVar GetGlobalVar(const std::string& str) const;
/*! /*!
* \brief Collect all global vars defined in this module.
* \returns An array of global vars
*/
tvm::Array<GlobalVar> GetGlobalVars() const;
/*!
* \brief Look up a global function by its name. * \brief Look up a global function by its name.
* \param str The unique string specifying the global variable. * \param str The unique string specifying the global variable.
* \returns The global variable. * \returns The global variable.
...@@ -138,6 +164,12 @@ class ModuleNode : public RelayNode { ...@@ -138,6 +164,12 @@ class ModuleNode : public RelayNode {
TVM_DLL GlobalTypeVar GetGlobalTypeVar(const std::string& str) const; TVM_DLL GlobalTypeVar GetGlobalTypeVar(const std::string& str) const;
/*! /*!
* \brief Collect all global type vars defined in this module.
* \returns An array of global type vars
*/
tvm::Array<GlobalTypeVar> GetGlobalTypeVars() const;
/*!
* \brief Look up a global function by its variable. * \brief Look up a global function by its variable.
* \param var The global var to lookup. * \param var The global var to lookup.
* \returns The function named by the variable argument. * \returns The function named by the variable argument.
......
...@@ -103,7 +103,8 @@ class PatternFunctor<R(const Pattern& n, Args...)> { ...@@ -103,7 +103,8 @@ class PatternFunctor<R(const Pattern& n, Args...)> {
virtual R VisitPattern_(const PatternTupleNode* op, virtual R VisitPattern_(const PatternTupleNode* op,
Args... args) PATTERN_FUNCTOR_DEFAULT; Args... args) PATTERN_FUNCTOR_DEFAULT;
virtual R VisitPatternDefault_(const Node* op, Args...) { virtual R VisitPatternDefault_(const Node* op, Args...) {
throw Error(std::string("Do not have a default for ") + op->type_key()); LOG(FATAL) << "Do not have a default for " << op->type_key();
throw;
} }
private: private:
......
...@@ -231,7 +231,7 @@ class ParseTreeToRelayIR(RelayVisitor): ...@@ -231,7 +231,7 @@ class ParseTreeToRelayIR(RelayVisitor):
def mk_typ(self, name: str, kind: ty.Kind) -> ty.TypeVar: def mk_typ(self, name: str, kind: ty.Kind) -> ty.TypeVar:
"""Create a new TypeVar and add it to the TypeVar scope.""" """Create a new TypeVar and add it to the TypeVar scope."""
typ = ty.TypeVar(name, kind) typ = ty.TypeVar(name, kind)
self.type_var_scopes[0].appendleft((name, typ)) self.type_var_scopes[0].append((name, typ))
return typ return typ
def mk_global_typ_var(self, name, kind): def mk_global_typ_var(self, name, kind):
...@@ -242,7 +242,7 @@ class ParseTreeToRelayIR(RelayVisitor): ...@@ -242,7 +242,7 @@ class ParseTreeToRelayIR(RelayVisitor):
self.global_type_vars[name] = typ self.global_type_vars[name] = typ
return typ return typ
# TODO: rethink whether we should have type constructors mixed with type vars. # TODO(weberlo): rethink whether we should have type constructors mixed with type vars.
def mk_global_typ_cons(self, name, cons): def mk_global_typ_cons(self, name, cons):
self._check_existing_typ_expr(name, cons) self._check_existing_typ_expr(name, cons)
self.global_type_vars[name] = cons self.global_type_vars[name] = cons
...@@ -291,11 +291,15 @@ class ParseTreeToRelayIR(RelayVisitor): ...@@ -291,11 +291,15 @@ class ParseTreeToRelayIR(RelayVisitor):
if name.startswith(type_prefix): if name.startswith(type_prefix):
return ty.scalar_type(name) return ty.scalar_type(name)
# Next, look it up in the local then global type params. # Next, look it up in the local then global type params.
type_param = lookup(self.type_var_scopes, name) type_expr = lookup(self.type_var_scopes, name)
if type_param is None: if type_expr is None:
type_param = self.global_type_vars.get(name, None) type_expr = self.global_type_vars.get(name, None)
if type_param is not None: if type_expr is not None:
return type_param # Zero-arity constructor calls fall into the general ident case, so in that case,
# we construct a constructor call with no args.
if isinstance(type_expr, adt.Constructor) and not type_expr.inputs:
type_expr = expr.Call(type_expr, [])
return type_expr
# Check if it's an operator. # Check if it's an operator.
op_name = ".".join([name.getText() for name in ctx.CNAME()]) op_name = ".".join([name.getText() for name in ctx.CNAME()])
if op_name in FUNC_OPS: if op_name in FUNC_OPS:
...@@ -321,14 +325,12 @@ class ParseTreeToRelayIR(RelayVisitor): ...@@ -321,14 +325,12 @@ class ParseTreeToRelayIR(RelayVisitor):
def visit_list(self, ctx_list) -> List[Any]: def visit_list(self, ctx_list) -> List[Any]:
""""Visit a list of contexts.""" """"Visit a list of contexts."""
# type: RelayParser.ContextParserRuleContext
assert isinstance(ctx_list, list) assert isinstance(ctx_list, list)
return [self.visit(ctx) for ctx in ctx_list] return [self.visit(ctx) for ctx in ctx_list]
def getTypeExpr(self, ctx) -> Optional[ty.Type]: def getTypeExpr(self, ctx: Optional[RelayParser.TypeExprContext]) -> Optional[ty.Type]:
"""Return a (possibly None) Relay type.""" """Return a (possibly None) Relay type."""
# type: : Optional[RelayParser.Type_Context]
if ctx is None: if ctx is None:
return None return None
...@@ -361,6 +363,10 @@ class ParseTreeToRelayIR(RelayVisitor): ...@@ -361,6 +363,10 @@ class ParseTreeToRelayIR(RelayVisitor):
return self.visit(ctx.expr()) return self.visit(ctx.expr())
# pass through # pass through
def visitTypeParen(self, ctx: RelayParser.TypeParenContext) -> expr.Expr:
return self.visit(ctx.typeExpr())
# pass through
def visitBody(self, ctx: RelayParser.BodyContext) -> expr.Expr: def visitBody(self, ctx: RelayParser.BodyContext) -> expr.Expr:
return self.visit(ctx.expr()) return self.visit(ctx.expr())
...@@ -466,7 +472,7 @@ class ParseTreeToRelayIR(RelayVisitor): ...@@ -466,7 +472,7 @@ class ParseTreeToRelayIR(RelayVisitor):
type_params = ctx.typeParamList() type_params = ctx.typeParamList()
if type_params is not None: if type_params is not None:
type_params = type_params.generalIdent() type_params = type_params.typeExpr()
assert type_params assert type_params
for ty_param in type_params: for ty_param in type_params:
name = ty_param.getText() name = ty_param.getText()
...@@ -498,7 +504,8 @@ class ParseTreeToRelayIR(RelayVisitor): ...@@ -498,7 +504,8 @@ class ParseTreeToRelayIR(RelayVisitor):
def visitFuncDefn(self, ctx: RelayParser.DefnContext) -> None: def visitFuncDefn(self, ctx: RelayParser.DefnContext) -> None:
ident_name = ctx.globalVar().getText()[1:] ident_name = ctx.globalVar().getText()[1:]
ident = self.mk_global_var(ident_name) ident = self.mk_global_var(ident_name)
self.module[ident] = self.mk_func(ctx) func = self.mk_func(ctx)
self.module[ident] = func
def handle_adt_header( def handle_adt_header(
self, self,
...@@ -512,7 +519,7 @@ class ParseTreeToRelayIR(RelayVisitor): ...@@ -512,7 +519,7 @@ class ParseTreeToRelayIR(RelayVisitor):
type_params = [] type_params = []
else: else:
type_params = [self.mk_typ(type_ident.getText(), ty.Kind.Type) type_params = [self.mk_typ(type_ident.getText(), ty.Kind.Type)
for type_ident in type_params.generalIdent()] for type_ident in type_params.typeExpr()]
return adt_var, type_params return adt_var, type_params
def visitExternAdtDefn(self, ctx: RelayParser.ExternAdtDefnContext): def visitExternAdtDefn(self, ctx: RelayParser.ExternAdtDefnContext):
...@@ -552,8 +559,6 @@ class ParseTreeToRelayIR(RelayVisitor): ...@@ -552,8 +559,6 @@ class ParseTreeToRelayIR(RelayVisitor):
else: else:
raise RuntimeError(f"unknown match type {match_type}") raise RuntimeError(f"unknown match type {match_type}")
# TODO: Will need some kind of type checking to know which ADT is being
# matched on.
match_data = self.visit(ctx.expr()) match_data = self.visit(ctx.expr())
match_clauses = ctx.matchClauseList() match_clauses = ctx.matchClauseList()
if match_clauses is None: if match_clauses is None:
...@@ -562,39 +567,36 @@ class ParseTreeToRelayIR(RelayVisitor): ...@@ -562,39 +567,36 @@ class ParseTreeToRelayIR(RelayVisitor):
match_clauses = match_clauses.matchClause() match_clauses = match_clauses.matchClause()
parsed_clauses = [] parsed_clauses = []
for clause in match_clauses: for clause in match_clauses:
constructor_name = clause.constructorName().getText()
constructor = self.global_type_vars[constructor_name]
self.enter_var_scope() self.enter_var_scope()
patternList = clause.patternList() pattern = self.visit(clause.pattern())
if patternList is None:
patterns = []
else:
patterns = [self.visit(pattern) for pattern in patternList.pattern()]
clause_body = self.visit(clause.expr()) clause_body = self.visit(clause.expr())
self.exit_var_scope() self.exit_var_scope()
# TODO: Do we need to pass `None` if it's a 0-arity cons, or is an empty list fine? parsed_clauses.append(adt.Clause(pattern, clause_body))
parsed_clauses.append(adt.Clause(
adt.PatternConstructor(
constructor,
patterns
),
clause_body
))
return adt.Match(match_data, parsed_clauses, complete=complete_match) return adt.Match(match_data, parsed_clauses, complete=complete_match)
def visitPattern(self, ctx: RelayParser.PatternContext): def visitWildcardPattern(self, ctx: RelayParser.WildcardPatternContext):
text = ctx.getText() return adt.PatternWildcard()
if text == "_":
return adt.PatternWildcard() def visitVarPattern(self, ctx: RelayParser.VarPatternContext):
elif text.startswith("%"): text = ctx.localVar().getText()
text = ctx.localVar().getText() typ = ctx.typeExpr()
typ = ctx.typeExpr() if typ is not None:
if typ is not None: typ = self.visit(typ)
typ = self.visit(typ) var = self.mk_var(text[1:], typ=typ)
var = self.mk_var(text[1:], typ=typ) return adt.PatternVar(var)
return adt.PatternVar(var)
def visitConstructorPattern(self, ctx: RelayParser.ConstructorPatternContext):
constructor_name = ctx.constructorName().getText()
constructor = self.global_type_vars[constructor_name]
pattern_list = ctx.patternList()
if pattern_list is None:
patterns = []
else: else:
raise ParseError(f"invalid pattern syntax \"{text}\"") patterns = [self.visit(pattern) for pattern in pattern_list.pattern()]
return adt.PatternConstructor(constructor, patterns)
def visitTuplePattern(self, ctx: RelayParser.TuplePatternContext):
return adt.PatternTuple([self.visit(pattern) for pattern in ctx.patternList().pattern()])
def visitCallNoAttr(self, ctx: RelayParser.CallNoAttrContext): def visitCallNoAttr(self, ctx: RelayParser.CallNoAttrContext):
return (self.visit_list(ctx.exprList().expr()), None) return (self.visit_list(ctx.exprList().expr()), None)
...@@ -610,16 +612,14 @@ class ParseTreeToRelayIR(RelayVisitor): ...@@ -610,16 +612,14 @@ class ParseTreeToRelayIR(RelayVisitor):
return expr.Call(func, args, attrs, type_args) return expr.Call(func, args, attrs, type_args)
@spanify @spanify
def visitCall(self, ctx: RelayParser.CallContext): def visitCall(self, ctx: RelayParser.CallContext) -> expr.Call:
# type: (RelayParser.CallContext) -> expr.Call
func = self.visit(ctx.expr()) func = self.visit(ctx.expr())
args, attrs = self.visit(ctx.callList()) args, attrs = self.visit(ctx.callList())
res = self.call(func, args, attrs, []) res = self.call(func, args, attrs, [])
return res return res
@spanify @spanify
def visitIfElse(self, ctx: RelayParser.IfElseContext): def visitIfElse(self, ctx: RelayParser.IfElseContext) -> expr.If:
# type: (RelayParser.IfElseContext) -> expr.If
"""Construct a Relay If node. Creates a new scope for each branch.""" """Construct a Relay If node. Creates a new scope for each branch."""
cond = self.visit(ctx.expr()) cond = self.visit(ctx.expr())
...@@ -634,8 +634,7 @@ class ParseTreeToRelayIR(RelayVisitor): ...@@ -634,8 +634,7 @@ class ParseTreeToRelayIR(RelayVisitor):
return expr.If(cond, true_branch, false_branch) return expr.If(cond, true_branch, false_branch)
@spanify @spanify
def visitGraph(self, ctx: RelayParser.GraphContext): def visitGraph(self, ctx: RelayParser.GraphContext) -> expr.Expr:
# type: (RelayParser.GraphContext) -> expr.Expr
"""Visit a graph variable assignment.""" """Visit a graph variable assignment."""
graph_nid = int(ctx.graphVar().getText()[1:]) graph_nid = int(ctx.graphVar().getText()[1:])
...@@ -655,28 +654,24 @@ class ParseTreeToRelayIR(RelayVisitor): ...@@ -655,28 +654,24 @@ class ParseTreeToRelayIR(RelayVisitor):
# Types # Types
# pylint: disable=unused-argument # pylint: disable=unused-argument
def visitIncompleteType(self, ctx: RelayParser.IncompleteTypeContext): def visitIncompleteType(self, ctx: RelayParser.IncompleteTypeContext) -> None:
# type (RelayParser.IncompleteTypeContext) -> None:
return None return None
def visitTypeCallType(self, ctx: RelayParser.TypeCallTypeContext): def visitTypeCallType(self, ctx: RelayParser.TypeCallTypeContext):
func = self.visit(ctx.generalIdent()) func = self.visit(ctx.generalIdent())
args = [self.visit(arg) for arg in ctx.typeParamList().generalIdent()] args = [self.visit(arg) for arg in ctx.typeParamList().typeExpr()]
return ty.TypeCall(func, args) return ty.TypeCall(func, args)
def visitParensShape(self, ctx: RelayParser.ParensShapeContext): def visitParensShape(self, ctx: RelayParser.ParensShapeContext) -> int:
# type: (RelayParser.ParensShapeContext) -> int
return self.visit(ctx.shape()) return self.visit(ctx.shape())
def visitShapeList(self, ctx: RelayParser.ShapeListContext): def visitShapeList(self, ctx: RelayParser.ShapeListContext) -> List[int]:
# type: (RelayParser.ShapeListContext) -> List[int]
return self.visit_list(ctx.shape()) return self.visit_list(ctx.shape())
def visitTensor(self, ctx: RelayParser.TensorContext): def visitTensor(self, ctx: RelayParser.TensorContext):
return tuple(self.visit_list(ctx.expr())) return tuple(self.visit_list(ctx.expr()))
def visitTensorType(self, ctx: RelayParser.TensorTypeContext): def visitTensorType(self, ctx: RelayParser.TensorTypeContext) -> ty.TensorType:
# type: (RelayParser.TensorTypeContext) -> ty.TensorType
"""Create a simple tensor type. No generics.""" """Create a simple tensor type. No generics."""
shape = self.visit(ctx.shapeList()) shape = self.visit(ctx.shapeList())
...@@ -689,12 +684,10 @@ class ParseTreeToRelayIR(RelayVisitor): ...@@ -689,12 +684,10 @@ class ParseTreeToRelayIR(RelayVisitor):
return ty.TensorType(shape, dtype) return ty.TensorType(shape, dtype)
def visitTupleType(self, ctx: RelayParser.TupleTypeContext): def visitTupleType(self, ctx: RelayParser.TupleTypeContext) -> ty.TupleType:
# type: (RelayParser.TupleTypeContext) -> ty.TupleType
return ty.TupleType(self.visit_list(ctx.typeExpr())) return ty.TupleType(self.visit_list(ctx.typeExpr()))
def visitFuncType(self, ctx: RelayParser.FuncTypeContext): def visitFuncType(self, ctx: RelayParser.FuncTypeContext) -> ty.FuncType:
# type: (RelayParser.FuncTypeContext) -> ty.FuncType
types = self.visit_list(ctx.typeExpr()) types = self.visit_list(ctx.typeExpr())
arg_types = types[:-1] arg_types = types[:-1]
...@@ -702,8 +695,7 @@ class ParseTreeToRelayIR(RelayVisitor): ...@@ -702,8 +695,7 @@ class ParseTreeToRelayIR(RelayVisitor):
return ty.FuncType(arg_types, ret_type, [], None) return ty.FuncType(arg_types, ret_type, [], None)
def make_parser(data): def make_parser(data: str) -> RelayParser:
# type: (str) -> RelayParser
"""Construct a RelayParser a given data stream.""" """Construct a RelayParser a given data stream."""
input_stream = InputStream(data) input_stream = InputStream(data)
lexer = RelayLexer(input_stream) lexer = RelayLexer(input_stream)
...@@ -738,8 +730,7 @@ class StrictErrorListener(ErrorListener): ...@@ -738,8 +730,7 @@ class StrictErrorListener(ErrorListener):
def reportContextSensitivity(self, recognizer, dfa, startIndex, stopIndex, prediction, configs): def reportContextSensitivity(self, recognizer, dfa, startIndex, stopIndex, prediction, configs):
raise Exception("Context Sensitivity in:\n" + self.text) raise Exception("Context Sensitivity in:\n" + self.text)
def fromtext(data, source_name=None): def fromtext(data: str, source_name: str = None) -> Union[expr.Expr, module.Module]:
# type: (str, str) -> Union[expr.Expr, module.Module]
"""Parse a Relay program.""" """Parse a Relay program."""
if data == "": if data == "":
raise ParseError("cannot parse the empty string.") raise ParseError("cannot parse the empty string.")
......
...@@ -87,33 +87,33 @@ callList ...@@ -87,33 +87,33 @@ callList
expr expr
// operators // operators
: '(' expr ')' # paren : '(' expr ')' # paren
// function application // function application
| expr '(' callList ')' # call | expr '(' callList ')' # call
| '-' expr # neg | '-' expr # neg
| expr op=('*'|'/') expr # binOp | expr op=('*'|'/') expr # binOp
| expr op=('+'|'-') expr # binOp | expr op=('+'|'-') expr # binOp
| expr op=('<'|'>'|'<='|'>=') expr # binOp | expr op=('<'|'>'|'<='|'>=') expr # binOp
| expr op=('=='|'!=') expr # binOp | expr op=('=='|'!=') expr # binOp
// function definition // function definition
| func # funcExpr | func # funcExpr
// tuples and tensors // tuples and tensors
| '(' ')' # tuple | '(' ')' # tuple
| '(' expr ',' ')' # tuple | '(' expr ',' ')' # tuple
| '(' expr (',' expr)+ ')' # tuple | '(' expr (',' expr)+ ')' # tuple
| '[' (expr (',' expr)*)? ']' # tensor | '[' (expr (',' expr)*)? ']' # tensor
| 'if' '(' expr ')' body 'else' body # ifElse | 'if' '(' expr ')' body 'else' body # ifElse
| matchType '(' expr ')' '{' matchClauseList? '}' # match | matchType expr '{' matchClauseList? '}' # match
| expr '.' NAT # projection | expr '.' NAT # projection
// sequencing // sequencing
| 'let' var '=' expr ';' expr # let | 'let' var '=' expr ';' expr # let
// sugar for let %_ = expr; expr // sugar for let %_ = expr; expr
| expr ';;' expr # let | expr ';;' expr # let
| graphVar '=' expr ';' expr # graph | graphVar '=' expr ';' expr # graph
| ident # identExpr | ident # identExpr
| scalar # scalarExpr | scalar # scalarExpr
| meta # metaExpr | meta # metaExpr
| QUOTED_STRING # stringExpr | QUOTED_STRING # stringExpr
; ;
func: 'fn' typeParamList? '(' argList ')' ('->' typeExpr)? body ; func: 'fn' typeParamList? '(' argList ')' ('->' typeExpr)? body ;
...@@ -128,14 +128,16 @@ constructorName: CNAME ; ...@@ -128,14 +128,16 @@ constructorName: CNAME ;
adtConsDefnList: adtConsDefn (',' adtConsDefn)* ','? ; adtConsDefnList: adtConsDefn (',' adtConsDefn)* ','? ;
adtConsDefn: constructorName ('(' typeExpr (',' typeExpr)* ')')? ; adtConsDefn: constructorName ('(' typeExpr (',' typeExpr)* ')')? ;
matchClauseList: matchClause (',' matchClause)* ','? ; matchClauseList: matchClause (',' matchClause)* ','? ;
matchClause: constructorName patternList? '=>' ('{' expr '}' | expr) ; matchClause: pattern '=>' ('{' expr '}' | expr) ;
// complete or incomplete match, respectively // complete or incomplete match, respectively
matchType : 'match' | 'match?' ; matchType : 'match' | 'match?' ;
patternList: '(' pattern (',' pattern)* ')'; patternList: '(' pattern (',' pattern)* ')';
pattern pattern
: '_' : '_' # wildcardPattern
| localVar (':' typeExpr)? | localVar (':' typeExpr)? # varPattern
| constructorName patternList? # constructorPattern
| patternList # tuplePattern
; ;
adtCons: constructorName adtConsParamList? ; adtCons: constructorName adtConsParamList? ;
...@@ -155,6 +157,7 @@ attr: CNAME '=' expr ; ...@@ -155,6 +157,7 @@ attr: CNAME '=' expr ;
typeExpr typeExpr
: '(' ')' # tupleType : '(' ')' # tupleType
| '(' typeExpr ')' # typeParen
| '(' typeExpr ',' ')' # tupleType | '(' typeExpr ',' ')' # tupleType
| '(' typeExpr (',' typeExpr)+ ')' # tupleType | '(' typeExpr (',' typeExpr)+ ')' # tupleType
| generalIdent typeParamList # typeCallType | generalIdent typeParamList # typeCallType
...@@ -164,7 +167,7 @@ typeExpr ...@@ -164,7 +167,7 @@ typeExpr
| '_' # incompleteType | '_' # incompleteType
; ;
typeParamList: '[' generalIdent (',' generalIdent)* ']' ; typeParamList: '[' typeExpr (',' typeExpr)* ']' ;
shapeList shapeList
: '(' ')' : '(' ')'
......
...@@ -9,7 +9,7 @@ import sys ...@@ -9,7 +9,7 @@ import sys
def serializedATN(): def serializedATN():
with StringIO() as buf: with StringIO() as buf:
buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\62") buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\62")
buf.write("\u01fc\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7") buf.write("\u0200\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7")
buf.write("\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t\13\4\f\t\f\4\r\t\r\4\16") buf.write("\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t\13\4\f\t\f\4\r\t\r\4\16")
buf.write("\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22\4\23\t\23") buf.write("\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22\4\23\t\23")
buf.write("\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31") buf.write("\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31")
...@@ -23,238 +23,241 @@ def serializedATN(): ...@@ -23,238 +23,241 @@ def serializedATN():
buf.write("\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\6\t\u0090\n\t\r\t\16\t") buf.write("\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\6\t\u0090\n\t\r\t\16\t")
buf.write("\u0091\3\t\3\t\3\t\3\t\3\t\3\t\7\t\u009a\n\t\f\t\16\t") buf.write("\u0091\3\t\3\t\3\t\3\t\3\t\3\t\7\t\u009a\n\t\f\t\16\t")
buf.write("\u009d\13\t\5\t\u009f\n\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t") buf.write("\u009d\13\t\5\t\u009f\n\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t")
buf.write("\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\5\t\u00b0\n\t\3\t\3\t") buf.write("\3\t\3\t\3\t\3\t\3\t\3\t\5\t\u00ae\n\t\3\t\3\t\3\t\3\t")
buf.write("\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3") buf.write("\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3")
buf.write("\t\3\t\3\t\3\t\5\t\u00c5\n\t\3\t\3\t\3\t\3\t\3\t\3\t\3") buf.write("\t\3\t\5\t\u00c3\n\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3")
buf.write("\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t") buf.write("\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t")
buf.write("\3\t\3\t\3\t\7\t\u00de\n\t\f\t\16\t\u00e1\13\t\3\n\3\n") buf.write("\3\t\7\t\u00dc\n\t\f\t\16\t\u00df\13\t\3\n\3\n\5\n\u00e3")
buf.write("\5\n\u00e5\n\n\3\n\3\n\3\n\3\n\3\n\5\n\u00ec\n\n\3\n\3") buf.write("\n\n\3\n\3\n\3\n\3\n\3\n\5\n\u00ea\n\n\3\n\3\n\3\13\3")
buf.write("\n\3\13\3\13\3\13\5\13\u00f3\n\13\3\13\3\13\3\13\3\13") buf.write("\13\3\13\5\13\u00f1\n\13\3\13\3\13\3\13\3\13\3\13\5\13")
buf.write("\3\13\5\13\u00fa\n\13\3\13\3\13\3\13\3\13\3\13\3\13\5") buf.write("\u00f8\n\13\3\13\3\13\3\13\3\13\3\13\3\13\5\13\u0100\n")
buf.write("\13\u0102\n\13\3\13\3\13\3\13\5\13\u0107\n\13\3\13\3\13") buf.write("\13\3\13\3\13\3\13\5\13\u0105\n\13\3\13\3\13\5\13\u0109")
buf.write("\5\13\u010b\n\13\3\13\3\13\5\13\u010f\n\13\3\f\3\f\3\r") buf.write("\n\13\3\13\3\13\5\13\u010d\n\13\3\f\3\f\3\r\3\r\3\r\7")
buf.write("\3\r\3\r\7\r\u0116\n\r\f\r\16\r\u0119\13\r\3\r\5\r\u011c") buf.write("\r\u0114\n\r\f\r\16\r\u0117\13\r\3\r\5\r\u011a\n\r\3\16")
buf.write("\n\r\3\16\3\16\3\16\3\16\3\16\7\16\u0123\n\16\f\16\16") buf.write("\3\16\3\16\3\16\3\16\7\16\u0121\n\16\f\16\16\16\u0124")
buf.write("\16\u0126\13\16\3\16\3\16\5\16\u012a\n\16\3\17\3\17\3") buf.write("\13\16\3\16\3\16\5\16\u0128\n\16\3\17\3\17\3\17\7\17\u012d")
buf.write("\17\7\17\u012f\n\17\f\17\16\17\u0132\13\17\3\17\5\17\u0135") buf.write("\n\17\f\17\16\17\u0130\13\17\3\17\5\17\u0133\n\17\3\20")
buf.write("\n\17\3\20\3\20\5\20\u0139\n\20\3\20\3\20\3\20\3\20\3") buf.write("\3\20\3\20\3\20\3\20\3\20\3\20\5\20\u013c\n\20\3\21\3")
buf.write("\20\3\20\5\20\u0141\n\20\3\21\3\21\3\22\3\22\3\22\3\22") buf.write("\21\3\22\3\22\3\22\3\22\7\22\u0144\n\22\f\22\16\22\u0147")
buf.write("\7\22\u0149\n\22\f\22\16\22\u014c\13\22\3\22\3\22\3\23") buf.write("\13\22\3\22\3\22\3\23\3\23\3\23\3\23\5\23\u014f\n\23\3")
buf.write("\3\23\3\23\3\23\5\23\u0154\n\23\5\23\u0156\n\23\3\24\3") buf.write("\23\3\23\5\23\u0153\n\23\3\23\5\23\u0156\n\23\3\24\3\24")
buf.write("\24\5\24\u015a\n\24\3\25\3\25\3\25\3\25\7\25\u0160\n\25") buf.write("\5\24\u015a\n\24\3\25\3\25\3\25\3\25\7\25\u0160\n\25\f")
buf.write("\f\25\16\25\u0163\13\25\3\25\3\25\3\26\3\26\5\26\u0169") buf.write("\25\16\25\u0163\13\25\3\25\3\25\3\26\3\26\5\26\u0169\n")
buf.write("\n\26\3\27\3\27\3\27\3\27\7\27\u016f\n\27\f\27\16\27\u0172") buf.write("\26\3\27\3\27\3\27\3\27\7\27\u016f\n\27\f\27\16\27\u0172")
buf.write("\13\27\3\27\5\27\u0175\n\27\3\30\3\30\3\30\7\30\u017a") buf.write("\13\27\3\27\5\27\u0175\n\27\3\30\3\30\3\30\7\30\u017a")
buf.write("\n\30\f\30\16\30\u017d\13\30\5\30\u017f\n\30\3\31\3\31") buf.write("\n\30\f\30\16\30\u017d\13\30\5\30\u017f\n\30\3\31\3\31")
buf.write("\3\31\5\31\u0184\n\31\3\32\3\32\3\32\7\32\u0189\n\32\f") buf.write("\3\31\5\31\u0184\n\31\3\32\3\32\3\32\7\32\u0189\n\32\f")
buf.write("\32\16\32\u018c\13\32\3\33\3\33\3\33\3\33\3\34\3\34\3") buf.write("\32\16\32\u018c\13\32\3\33\3\33\3\33\3\33\3\34\3\34\3")
buf.write("\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\6\34\u019d") buf.write("\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34")
buf.write("\n\34\r\34\16\34\u019e\3\34\3\34\3\34\3\34\3\34\3\34\3") buf.write("\3\34\3\34\6\34\u01a1\n\34\r\34\16\34\u01a2\3\34\3\34")
buf.write("\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\5\34\u01b0") buf.write("\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34")
buf.write("\n\34\3\34\3\34\3\34\3\34\7\34\u01b6\n\34\f\34\16\34\u01b9") buf.write("\3\34\3\34\5\34\u01b4\n\34\3\34\3\34\3\34\3\34\7\34\u01ba")
buf.write("\13\34\5\34\u01bb\n\34\3\34\3\34\3\34\3\34\5\34\u01c1") buf.write("\n\34\f\34\16\34\u01bd\13\34\5\34\u01bf\n\34\3\34\3\34")
buf.write("\n\34\3\35\3\35\3\35\3\35\7\35\u01c7\n\35\f\35\16\35\u01ca") buf.write("\3\34\3\34\5\34\u01c5\n\34\3\35\3\35\3\35\3\35\7\35\u01cb")
buf.write("\13\35\3\35\3\35\3\36\3\36\3\36\3\36\3\36\3\36\6\36\u01d4") buf.write("\n\35\f\35\16\35\u01ce\13\35\3\35\3\35\3\36\3\36\3\36")
buf.write("\n\36\r\36\16\36\u01d5\3\36\3\36\3\36\5\36\u01db\n\36") buf.write("\3\36\3\36\3\36\6\36\u01d8\n\36\r\36\16\36\u01d9\3\36")
buf.write("\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3 \3 \3 \3 \3") buf.write("\3\36\3\36\5\36\u01df\n\36\3\37\3\37\3\37\3\37\3\37\3")
buf.write(" \3 \5 \u01eb\n \3!\3!\3!\3!\3\"\3\"\3\"\5\"\u01f4\n\"") buf.write("\37\3\37\3\37\3 \3 \3 \3 \3 \3 \5 \u01ef\n \3!\3!\3!\3")
buf.write("\3#\3#\3#\3#\5#\u01fa\n#\3#\2\3\20$\2\4\6\b\n\f\16\20") buf.write("!\3\"\3\"\3\"\5\"\u01f8\n\"\3#\3#\3#\3#\5#\u01fe\n#\3")
buf.write("\22\24\26\30\32\34\36 \"$&(*,.\60\62\64\668:<>@BD\2\b") buf.write("#\2\3\20$\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&")
buf.write("\4\2\6\6//\3\2$%\3\2&\'\3\2(+\3\2,-\3\2\32\33\2\u022d") buf.write("(*,.\60\62\64\668:<>@BD\2\b\4\2\6\6//\3\2$%\3\2&\'\3\2")
buf.write("\2F\3\2\2\2\4U\3\2\2\2\6]\3\2\2\2\b`\3\2\2\2\nc\3\2\2") buf.write("(+\3\2,-\3\2\32\33\2\u0234\2F\3\2\2\2\4U\3\2\2\2\6]\3")
buf.write("\2\fn\3\2\2\2\16z\3\2\2\2\20\u00c4\3\2\2\2\22\u00e2\3") buf.write("\2\2\2\b`\3\2\2\2\nc\3\2\2\2\fn\3\2\2\2\16z\3\2\2\2\20")
buf.write("\2\2\2\24\u010e\3\2\2\2\26\u0110\3\2\2\2\30\u0112\3\2") buf.write("\u00c2\3\2\2\2\22\u00e0\3\2\2\2\24\u010c\3\2\2\2\26\u010e")
buf.write("\2\2\32\u011d\3\2\2\2\34\u012b\3\2\2\2\36\u0136\3\2\2") buf.write("\3\2\2\2\30\u0110\3\2\2\2\32\u011b\3\2\2\2\34\u0129\3")
buf.write("\2 \u0142\3\2\2\2\"\u0144\3\2\2\2$\u0155\3\2\2\2&\u0157") buf.write("\2\2\2\36\u0134\3\2\2\2 \u013d\3\2\2\2\"\u013f\3\2\2\2")
buf.write("\3\2\2\2(\u015b\3\2\2\2*\u0168\3\2\2\2,\u0174\3\2\2\2") buf.write("$\u0155\3\2\2\2&\u0157\3\2\2\2(\u015b\3\2\2\2*\u0168\3")
buf.write(".\u017e\3\2\2\2\60\u0180\3\2\2\2\62\u0185\3\2\2\2\64\u018d") buf.write("\2\2\2,\u0174\3\2\2\2.\u017e\3\2\2\2\60\u0180\3\2\2\2")
buf.write("\3\2\2\2\66\u01c0\3\2\2\28\u01c2\3\2\2\2:\u01da\3\2\2") buf.write("\62\u0185\3\2\2\2\64\u018d\3\2\2\2\66\u01c4\3\2\2\28\u01c6")
buf.write("\2<\u01dc\3\2\2\2>\u01ea\3\2\2\2@\u01ec\3\2\2\2B\u01f3") buf.write("\3\2\2\2:\u01de\3\2\2\2<\u01e0\3\2\2\2>\u01ee\3\2\2\2")
buf.write("\3\2\2\2D\u01f9\3\2\2\2FN\7\37\2\2GI\5\24\13\2HG\3\2\2") buf.write("@\u01f0\3\2\2\2B\u01f7\3\2\2\2D\u01fd\3\2\2\2FN\7\37\2")
buf.write("\2IL\3\2\2\2JH\3\2\2\2JK\3\2\2\2KO\3\2\2\2LJ\3\2\2\2M") buf.write("\2GI\5\24\13\2HG\3\2\2\2IL\3\2\2\2JH\3\2\2\2JK\3\2\2\2")
buf.write("O\5\20\t\2NJ\3\2\2\2NM\3\2\2\2OQ\3\2\2\2PR\7\62\2\2QP") buf.write("KO\3\2\2\2LJ\3\2\2\2MO\5\20\t\2NJ\3\2\2\2NM\3\2\2\2OQ")
buf.write("\3\2\2\2QR\3\2\2\2RS\3\2\2\2ST\7\2\2\3T\3\3\2\2\2UZ\7") buf.write("\3\2\2\2PR\7\62\2\2QP\3\2\2\2QR\3\2\2\2RS\3\2\2\2ST\7")
buf.write("/\2\2VW\7\3\2\2WY\7/\2\2XV\3\2\2\2Y\\\3\2\2\2ZX\3\2\2") buf.write("\2\2\3T\3\3\2\2\2UZ\7/\2\2VW\7\3\2\2WY\7/\2\2XV\3\2\2")
buf.write("\2Z[\3\2\2\2[\5\3\2\2\2\\Z\3\2\2\2]^\7\4\2\2^_\7/\2\2") buf.write("\2Y\\\3\2\2\2ZX\3\2\2\2Z[\3\2\2\2[\5\3\2\2\2\\Z\3\2\2")
buf.write("_\7\3\2\2\2`a\7\5\2\2ab\t\2\2\2b\t\3\2\2\2cd\7\5\2\2d") buf.write("\2]^\7\4\2\2^_\7/\2\2_\7\3\2\2\2`a\7\5\2\2ab\t\2\2\2b")
buf.write("e\7\61\2\2e\13\3\2\2\2fk\5\20\t\2gh\7\7\2\2hj\5\20\t\2") buf.write("\t\3\2\2\2cd\7\5\2\2de\7\61\2\2e\13\3\2\2\2fk\5\20\t\2")
buf.write("ig\3\2\2\2jm\3\2\2\2ki\3\2\2\2kl\3\2\2\2lo\3\2\2\2mk\3") buf.write("gh\7\7\2\2hj\5\20\t\2ig\3\2\2\2jm\3\2\2\2ki\3\2\2\2kl")
buf.write("\2\2\2nf\3\2\2\2no\3\2\2\2o\r\3\2\2\2p{\5\f\7\2qr\5\20") buf.write("\3\2\2\2lo\3\2\2\2mk\3\2\2\2nf\3\2\2\2no\3\2\2\2o\r\3")
buf.write("\t\2rs\7\7\2\2su\3\2\2\2tq\3\2\2\2ux\3\2\2\2vt\3\2\2\2") buf.write("\2\2\2p{\5\f\7\2qr\5\20\t\2rs\7\7\2\2su\3\2\2\2tq\3\2")
buf.write("vw\3\2\2\2wy\3\2\2\2xv\3\2\2\2y{\5\62\32\2zp\3\2\2\2z") buf.write("\2\2ux\3\2\2\2vt\3\2\2\2vw\3\2\2\2wy\3\2\2\2xv\3\2\2\2")
buf.write("v\3\2\2\2{\17\3\2\2\2|}\b\t\1\2}~\7\b\2\2~\177\5\20\t") buf.write("y{\5\62\32\2zp\3\2\2\2zv\3\2\2\2{\17\3\2\2\2|}\b\t\1\2")
buf.write("\2\177\u0080\7\t\2\2\u0080\u00c5\3\2\2\2\u0081\u0082\7") buf.write("}~\7\b\2\2~\177\5\20\t\2\177\u0080\7\t\2\2\u0080\u00c3")
buf.write("\'\2\2\u0082\u00c5\5\20\t\26\u0083\u00c5\5\22\n\2\u0084") buf.write("\3\2\2\2\u0081\u0082\7\'\2\2\u0082\u00c3\5\20\t\26\u0083")
buf.write("\u0085\7\b\2\2\u0085\u00c5\7\t\2\2\u0086\u0087\7\b\2\2") buf.write("\u00c3\5\22\n\2\u0084\u0085\7\b\2\2\u0085\u00c3\7\t\2")
buf.write("\u0087\u0088\5\20\t\2\u0088\u0089\7\7\2\2\u0089\u008a") buf.write("\2\u0086\u0087\7\b\2\2\u0087\u0088\5\20\t\2\u0088\u0089")
buf.write("\7\t\2\2\u008a\u00c5\3\2\2\2\u008b\u008c\7\b\2\2\u008c") buf.write("\7\7\2\2\u0089\u008a\7\t\2\2\u008a\u00c3\3\2\2\2\u008b")
buf.write("\u008f\5\20\t\2\u008d\u008e\7\7\2\2\u008e\u0090\5\20\t") buf.write("\u008c\7\b\2\2\u008c\u008f\5\20\t\2\u008d\u008e\7\7\2")
buf.write("\2\u008f\u008d\3\2\2\2\u0090\u0091\3\2\2\2\u0091\u008f") buf.write("\2\u008e\u0090\5\20\t\2\u008f\u008d\3\2\2\2\u0090\u0091")
buf.write("\3\2\2\2\u0091\u0092\3\2\2\2\u0092\u0093\3\2\2\2\u0093") buf.write("\3\2\2\2\u0091\u008f\3\2\2\2\u0091\u0092\3\2\2\2\u0092")
buf.write("\u0094\7\t\2\2\u0094\u00c5\3\2\2\2\u0095\u009e\7\n\2\2") buf.write("\u0093\3\2\2\2\u0093\u0094\7\t\2\2\u0094\u00c3\3\2\2\2")
buf.write("\u0096\u009b\5\20\t\2\u0097\u0098\7\7\2\2\u0098\u009a") buf.write("\u0095\u009e\7\n\2\2\u0096\u009b\5\20\t\2\u0097\u0098")
buf.write("\5\20\t\2\u0099\u0097\3\2\2\2\u009a\u009d\3\2\2\2\u009b") buf.write("\7\7\2\2\u0098\u009a\5\20\t\2\u0099\u0097\3\2\2\2\u009a")
buf.write("\u0099\3\2\2\2\u009b\u009c\3\2\2\2\u009c\u009f\3\2\2\2") buf.write("\u009d\3\2\2\2\u009b\u0099\3\2\2\2\u009b\u009c\3\2\2\2")
buf.write("\u009d\u009b\3\2\2\2\u009e\u0096\3\2\2\2\u009e\u009f\3") buf.write("\u009c\u009f\3\2\2\2\u009d\u009b\3\2\2\2\u009e\u0096\3")
buf.write("\2\2\2\u009f\u00a0\3\2\2\2\u00a0\u00c5\7\13\2\2\u00a1") buf.write("\2\2\2\u009e\u009f\3\2\2\2\u009f\u00a0\3\2\2\2\u00a0\u00c3")
buf.write("\u00a2\7\f\2\2\u00a2\u00a3\7\b\2\2\u00a3\u00a4\5\20\t") buf.write("\7\13\2\2\u00a1\u00a2\7\f\2\2\u00a2\u00a3\7\b\2\2\u00a3")
buf.write("\2\u00a4\u00a5\7\t\2\2\u00a5\u00a6\5@!\2\u00a6\u00a7\7") buf.write("\u00a4\5\20\t\2\u00a4\u00a5\7\t\2\2\u00a5\u00a6\5@!\2")
buf.write("\r\2\2\u00a7\u00a8\5@!\2\u00a8\u00c5\3\2\2\2\u00a9\u00aa") buf.write("\u00a6\u00a7\7\r\2\2\u00a7\u00a8\5@!\2\u00a8\u00c3\3\2")
buf.write("\5 \21\2\u00aa\u00ab\7\b\2\2\u00ab\u00ac\5\20\t\2\u00ac") buf.write("\2\2\u00a9\u00aa\5 \21\2\u00aa\u00ab\5\20\t\2\u00ab\u00ad")
buf.write("\u00ad\7\t\2\2\u00ad\u00af\7\16\2\2\u00ae\u00b0\5\34\17") buf.write("\7\16\2\2\u00ac\u00ae\5\34\17\2\u00ad\u00ac\3\2\2\2\u00ad")
buf.write("\2\u00af\u00ae\3\2\2\2\u00af\u00b0\3\2\2\2\u00b0\u00b1") buf.write("\u00ae\3\2\2\2\u00ae\u00af\3\2\2\2\u00af\u00b0\7\17\2")
buf.write("\3\2\2\2\u00b1\u00b2\7\17\2\2\u00b2\u00c5\3\2\2\2\u00b3") buf.write("\2\u00b0\u00c3\3\2\2\2\u00b1\u00b2\7\20\2\2\u00b2\u00b3")
buf.write("\u00b4\7\20\2\2\u00b4\u00b5\5\60\31\2\u00b5\u00b6\7\21") buf.write("\5\60\31\2\u00b3\u00b4\7\21\2\2\u00b4\u00b5\5\20\t\2\u00b5")
buf.write("\2\2\u00b6\u00b7\5\20\t\2\u00b7\u00b8\7\22\2\2\u00b8\u00b9") buf.write("\u00b6\7\22\2\2\u00b6\u00b7\5\20\t\t\u00b7\u00c3\3\2\2")
buf.write("\5\20\t\t\u00b9\u00c5\3\2\2\2\u00ba\u00bb\5\n\6\2\u00bb") buf.write("\2\u00b8\u00b9\5\n\6\2\u00b9\u00ba\7\21\2\2\u00ba\u00bb")
buf.write("\u00bc\7\21\2\2\u00bc\u00bd\5\20\t\2\u00bd\u00be\7\22") buf.write("\5\20\t\2\u00bb\u00bc\7\22\2\2\u00bc\u00bd\5\20\t\7\u00bd")
buf.write("\2\2\u00be\u00bf\5\20\t\7\u00bf\u00c5\3\2\2\2\u00c0\u00c5") buf.write("\u00c3\3\2\2\2\u00be\u00c3\5D#\2\u00bf\u00c3\5B\"\2\u00c0")
buf.write("\5D#\2\u00c1\u00c5\5B\"\2\u00c2\u00c5\5<\37\2\u00c3\u00c5") buf.write("\u00c3\5<\37\2\u00c1\u00c3\7#\2\2\u00c2|\3\2\2\2\u00c2")
buf.write("\7#\2\2\u00c4|\3\2\2\2\u00c4\u0081\3\2\2\2\u00c4\u0083") buf.write("\u0081\3\2\2\2\u00c2\u0083\3\2\2\2\u00c2\u0084\3\2\2\2")
buf.write("\3\2\2\2\u00c4\u0084\3\2\2\2\u00c4\u0086\3\2\2\2\u00c4") buf.write("\u00c2\u0086\3\2\2\2\u00c2\u008b\3\2\2\2\u00c2\u0095\3")
buf.write("\u008b\3\2\2\2\u00c4\u0095\3\2\2\2\u00c4\u00a1\3\2\2\2") buf.write("\2\2\2\u00c2\u00a1\3\2\2\2\u00c2\u00a9\3\2\2\2\u00c2\u00b1")
buf.write("\u00c4\u00a9\3\2\2\2\u00c4\u00b3\3\2\2\2\u00c4\u00ba\3") buf.write("\3\2\2\2\u00c2\u00b8\3\2\2\2\u00c2\u00be\3\2\2\2\u00c2")
buf.write("\2\2\2\u00c4\u00c0\3\2\2\2\u00c4\u00c1\3\2\2\2\u00c4\u00c2") buf.write("\u00bf\3\2\2\2\u00c2\u00c0\3\2\2\2\u00c2\u00c1\3\2\2\2")
buf.write("\3\2\2\2\u00c4\u00c3\3\2\2\2\u00c5\u00df\3\2\2\2\u00c6") buf.write("\u00c3\u00dd\3\2\2\2\u00c4\u00c5\f\25\2\2\u00c5\u00c6")
buf.write("\u00c7\f\25\2\2\u00c7\u00c8\t\3\2\2\u00c8\u00de\5\20\t") buf.write("\t\3\2\2\u00c6\u00dc\5\20\t\26\u00c7\u00c8\f\24\2\2\u00c8")
buf.write("\26\u00c9\u00ca\f\24\2\2\u00ca\u00cb\t\4\2\2\u00cb\u00de") buf.write("\u00c9\t\4\2\2\u00c9\u00dc\5\20\t\25\u00ca\u00cb\f\23")
buf.write("\5\20\t\25\u00cc\u00cd\f\23\2\2\u00cd\u00ce\t\5\2\2\u00ce") buf.write("\2\2\u00cb\u00cc\t\5\2\2\u00cc\u00dc\5\20\t\24\u00cd\u00ce")
buf.write("\u00de\5\20\t\24\u00cf\u00d0\f\22\2\2\u00d0\u00d1\t\6") buf.write("\f\22\2\2\u00ce\u00cf\t\6\2\2\u00cf\u00dc\5\20\t\23\u00d0")
buf.write("\2\2\u00d1\u00de\5\20\t\23\u00d2\u00d3\f\b\2\2\u00d3\u00d4") buf.write("\u00d1\f\b\2\2\u00d1\u00d2\7\23\2\2\u00d2\u00dc\5\20\t")
buf.write("\7\23\2\2\u00d4\u00de\5\20\t\t\u00d5\u00d6\f\27\2\2\u00d6") buf.write("\t\u00d3\u00d4\f\27\2\2\u00d4\u00d5\7\b\2\2\u00d5\u00d6")
buf.write("\u00d7\7\b\2\2\u00d7\u00d8\5\16\b\2\u00d8\u00d9\7\t\2") buf.write("\5\16\b\2\u00d6\u00d7\7\t\2\2\u00d7\u00dc\3\2\2\2\u00d8")
buf.write("\2\u00d9\u00de\3\2\2\2\u00da\u00db\f\n\2\2\u00db\u00dc") buf.write("\u00d9\f\n\2\2\u00d9\u00da\7\3\2\2\u00da\u00dc\7\61\2")
buf.write("\7\3\2\2\u00dc\u00de\7\61\2\2\u00dd\u00c6\3\2\2\2\u00dd") buf.write("\2\u00db\u00c4\3\2\2\2\u00db\u00c7\3\2\2\2\u00db\u00ca")
buf.write("\u00c9\3\2\2\2\u00dd\u00cc\3\2\2\2\u00dd\u00cf\3\2\2\2") buf.write("\3\2\2\2\u00db\u00cd\3\2\2\2\u00db\u00d0\3\2\2\2\u00db")
buf.write("\u00dd\u00d2\3\2\2\2\u00dd\u00d5\3\2\2\2\u00dd\u00da\3") buf.write("\u00d3\3\2\2\2\u00db\u00d8\3\2\2\2\u00dc\u00df\3\2\2\2")
buf.write("\2\2\2\u00de\u00e1\3\2\2\2\u00df\u00dd\3\2\2\2\u00df\u00e0") buf.write("\u00dd\u00db\3\2\2\2\u00dd\u00de\3\2\2\2\u00de\21\3\2")
buf.write("\3\2\2\2\u00e0\21\3\2\2\2\u00e1\u00df\3\2\2\2\u00e2\u00e4") buf.write("\2\2\u00df\u00dd\3\2\2\2\u00e0\u00e2\7\24\2\2\u00e1\u00e3")
buf.write("\7\24\2\2\u00e3\u00e5\58\35\2\u00e4\u00e3\3\2\2\2\u00e4") buf.write("\58\35\2\u00e2\u00e1\3\2\2\2\u00e2\u00e3\3\2\2\2\u00e3")
buf.write("\u00e5\3\2\2\2\u00e5\u00e6\3\2\2\2\u00e6\u00e7\7\b\2\2") buf.write("\u00e4\3\2\2\2\u00e4\u00e5\7\b\2\2\u00e5\u00e6\5,\27\2")
buf.write("\u00e7\u00e8\5,\27\2\u00e8\u00eb\7\t\2\2\u00e9\u00ea\7") buf.write("\u00e6\u00e9\7\t\2\2\u00e7\u00e8\7\25\2\2\u00e8\u00ea")
buf.write("\25\2\2\u00ea\u00ec\5\66\34\2\u00eb\u00e9\3\2\2\2\u00eb") buf.write("\5\66\34\2\u00e9\u00e7\3\2\2\2\u00e9\u00ea\3\2\2\2\u00ea")
buf.write("\u00ec\3\2\2\2\u00ec\u00ed\3\2\2\2\u00ed\u00ee\5@!\2\u00ee") buf.write("\u00eb\3\2\2\2\u00eb\u00ec\5@!\2\u00ec\23\3\2\2\2\u00ed")
buf.write("\23\3\2\2\2\u00ef\u00f0\7\26\2\2\u00f0\u00f2\5\6\4\2\u00f1") buf.write("\u00ee\7\26\2\2\u00ee\u00f0\5\6\4\2\u00ef\u00f1\58\35")
buf.write("\u00f3\58\35\2\u00f2\u00f1\3\2\2\2\u00f2\u00f3\3\2\2\2") buf.write("\2\u00f0\u00ef\3\2\2\2\u00f0\u00f1\3\2\2\2\u00f1\u00f2")
buf.write("\u00f3\u00f4\3\2\2\2\u00f4\u00f5\7\b\2\2\u00f5\u00f6\5") buf.write("\3\2\2\2\u00f2\u00f3\7\b\2\2\u00f3\u00f4\5,\27\2\u00f4")
buf.write(",\27\2\u00f6\u00f9\7\t\2\2\u00f7\u00f8\7\25\2\2\u00f8") buf.write("\u00f7\7\t\2\2\u00f5\u00f6\7\25\2\2\u00f6\u00f8\5\66\34")
buf.write("\u00fa\5\66\34\2\u00f9\u00f7\3\2\2\2\u00f9\u00fa\3\2\2") buf.write("\2\u00f7\u00f5\3\2\2\2\u00f7\u00f8\3\2\2\2\u00f8\u00f9")
buf.write("\2\u00fa\u00fb\3\2\2\2\u00fb\u00fc\5@!\2\u00fc\u010f\3") buf.write("\3\2\2\2\u00f9\u00fa\5@!\2\u00fa\u010d\3\2\2\2\u00fb\u00fc")
buf.write("\2\2\2\u00fd\u00fe\7\27\2\2\u00fe\u00ff\7\30\2\2\u00ff") buf.write("\7\27\2\2\u00fc\u00fd\7\30\2\2\u00fd\u00ff\5\4\3\2\u00fe")
buf.write("\u0101\5\4\3\2\u0100\u0102\58\35\2\u0101\u0100\3\2\2\2") buf.write("\u0100\58\35\2\u00ff\u00fe\3\2\2\2\u00ff\u0100\3\2\2\2")
buf.write("\u0101\u0102\3\2\2\2\u0102\u010f\3\2\2\2\u0103\u0104\7") buf.write("\u0100\u010d\3\2\2\2\u0101\u0102\7\30\2\2\u0102\u0104")
buf.write("\30\2\2\u0104\u0106\5\4\3\2\u0105\u0107\58\35\2\u0106") buf.write("\5\4\3\2\u0103\u0105\58\35\2\u0104\u0103\3\2\2\2\u0104")
buf.write("\u0105\3\2\2\2\u0106\u0107\3\2\2\2\u0107\u0108\3\2\2\2") buf.write("\u0105\3\2\2\2\u0105\u0106\3\2\2\2\u0106\u0108\7\16\2")
buf.write("\u0108\u010a\7\16\2\2\u0109\u010b\5\30\r\2\u010a\u0109") buf.write("\2\u0107\u0109\5\30\r\2\u0108\u0107\3\2\2\2\u0108\u0109")
buf.write("\3\2\2\2\u010a\u010b\3\2\2\2\u010b\u010c\3\2\2\2\u010c") buf.write("\3\2\2\2\u0109\u010a\3\2\2\2\u010a\u010b\7\17\2\2\u010b")
buf.write("\u010d\7\17\2\2\u010d\u010f\3\2\2\2\u010e\u00ef\3\2\2") buf.write("\u010d\3\2\2\2\u010c\u00ed\3\2\2\2\u010c\u00fb\3\2\2\2")
buf.write("\2\u010e\u00fd\3\2\2\2\u010e\u0103\3\2\2\2\u010f\25\3") buf.write("\u010c\u0101\3\2\2\2\u010d\25\3\2\2\2\u010e\u010f\7/\2")
buf.write("\2\2\2\u0110\u0111\7/\2\2\u0111\27\3\2\2\2\u0112\u0117") buf.write("\2\u010f\27\3\2\2\2\u0110\u0115\5\32\16\2\u0111\u0112")
buf.write("\5\32\16\2\u0113\u0114\7\7\2\2\u0114\u0116\5\32\16\2\u0115") buf.write("\7\7\2\2\u0112\u0114\5\32\16\2\u0113\u0111\3\2\2\2\u0114")
buf.write("\u0113\3\2\2\2\u0116\u0119\3\2\2\2\u0117\u0115\3\2\2\2") buf.write("\u0117\3\2\2\2\u0115\u0113\3\2\2\2\u0115\u0116\3\2\2\2")
buf.write("\u0117\u0118\3\2\2\2\u0118\u011b\3\2\2\2\u0119\u0117\3") buf.write("\u0116\u0119\3\2\2\2\u0117\u0115\3\2\2\2\u0118\u011a\7")
buf.write("\2\2\2\u011a\u011c\7\7\2\2\u011b\u011a\3\2\2\2\u011b\u011c") buf.write("\7\2\2\u0119\u0118\3\2\2\2\u0119\u011a\3\2\2\2\u011a\31")
buf.write("\3\2\2\2\u011c\31\3\2\2\2\u011d\u0129\5\26\f\2\u011e\u011f") buf.write("\3\2\2\2\u011b\u0127\5\26\f\2\u011c\u011d\7\b\2\2\u011d")
buf.write("\7\b\2\2\u011f\u0124\5\66\34\2\u0120\u0121\7\7\2\2\u0121") buf.write("\u0122\5\66\34\2\u011e\u011f\7\7\2\2\u011f\u0121\5\66")
buf.write("\u0123\5\66\34\2\u0122\u0120\3\2\2\2\u0123\u0126\3\2\2") buf.write("\34\2\u0120\u011e\3\2\2\2\u0121\u0124\3\2\2\2\u0122\u0120")
buf.write("\2\u0124\u0122\3\2\2\2\u0124\u0125\3\2\2\2\u0125\u0127") buf.write("\3\2\2\2\u0122\u0123\3\2\2\2\u0123\u0125\3\2\2\2\u0124")
buf.write("\3\2\2\2\u0126\u0124\3\2\2\2\u0127\u0128\7\t\2\2\u0128") buf.write("\u0122\3\2\2\2\u0125\u0126\7\t\2\2\u0126\u0128\3\2\2\2")
buf.write("\u012a\3\2\2\2\u0129\u011e\3\2\2\2\u0129\u012a\3\2\2\2") buf.write("\u0127\u011c\3\2\2\2\u0127\u0128\3\2\2\2\u0128\33\3\2")
buf.write("\u012a\33\3\2\2\2\u012b\u0130\5\36\20\2\u012c\u012d\7") buf.write("\2\2\u0129\u012e\5\36\20\2\u012a\u012b\7\7\2\2\u012b\u012d")
buf.write("\7\2\2\u012d\u012f\5\36\20\2\u012e\u012c\3\2\2\2\u012f") buf.write("\5\36\20\2\u012c\u012a\3\2\2\2\u012d\u0130\3\2\2\2\u012e")
buf.write("\u0132\3\2\2\2\u0130\u012e\3\2\2\2\u0130\u0131\3\2\2\2") buf.write("\u012c\3\2\2\2\u012e\u012f\3\2\2\2\u012f\u0132\3\2\2\2")
buf.write("\u0131\u0134\3\2\2\2\u0132\u0130\3\2\2\2\u0133\u0135\7") buf.write("\u0130\u012e\3\2\2\2\u0131\u0133\7\7\2\2\u0132\u0131\3")
buf.write("\7\2\2\u0134\u0133\3\2\2\2\u0134\u0135\3\2\2\2\u0135\35") buf.write("\2\2\2\u0132\u0133\3\2\2\2\u0133\35\3\2\2\2\u0134\u0135")
buf.write("\3\2\2\2\u0136\u0138\5\26\f\2\u0137\u0139\5\"\22\2\u0138") buf.write("\5$\23\2\u0135\u013b\7\31\2\2\u0136\u0137\7\16\2\2\u0137")
buf.write("\u0137\3\2\2\2\u0138\u0139\3\2\2\2\u0139\u013a\3\2\2\2") buf.write("\u0138\5\20\t\2\u0138\u0139\7\17\2\2\u0139\u013c\3\2\2")
buf.write("\u013a\u0140\7\31\2\2\u013b\u013c\7\16\2\2\u013c\u013d") buf.write("\2\u013a\u013c\5\20\t\2\u013b\u0136\3\2\2\2\u013b\u013a")
buf.write("\5\20\t\2\u013d\u013e\7\17\2\2\u013e\u0141\3\2\2\2\u013f") buf.write("\3\2\2\2\u013c\37\3\2\2\2\u013d\u013e\t\7\2\2\u013e!\3")
buf.write("\u0141\5\20\t\2\u0140\u013b\3\2\2\2\u0140\u013f\3\2\2") buf.write("\2\2\2\u013f\u0140\7\b\2\2\u0140\u0145\5$\23\2\u0141\u0142")
buf.write("\2\u0141\37\3\2\2\2\u0142\u0143\t\7\2\2\u0143!\3\2\2\2") buf.write("\7\7\2\2\u0142\u0144\5$\23\2\u0143\u0141\3\2\2\2\u0144")
buf.write("\u0144\u0145\7\b\2\2\u0145\u014a\5$\23\2\u0146\u0147\7") buf.write("\u0147\3\2\2\2\u0145\u0143\3\2\2\2\u0145\u0146\3\2\2\2")
buf.write("\7\2\2\u0147\u0149\5$\23\2\u0148\u0146\3\2\2\2\u0149\u014c") buf.write("\u0146\u0148\3\2\2\2\u0147\u0145\3\2\2\2\u0148\u0149\7")
buf.write("\3\2\2\2\u014a\u0148\3\2\2\2\u014a\u014b\3\2\2\2\u014b") buf.write("\t\2\2\u0149#\3\2\2\2\u014a\u0156\7\6\2\2\u014b\u014e")
buf.write("\u014d\3\2\2\2\u014c\u014a\3\2\2\2\u014d\u014e\7\t\2\2") buf.write("\5\b\5\2\u014c\u014d\7\34\2\2\u014d\u014f\5\66\34\2\u014e")
buf.write("\u014e#\3\2\2\2\u014f\u0156\7\6\2\2\u0150\u0153\5\b\5") buf.write("\u014c\3\2\2\2\u014e\u014f\3\2\2\2\u014f\u0156\3\2\2\2")
buf.write("\2\u0151\u0152\7\34\2\2\u0152\u0154\5\66\34\2\u0153\u0151") buf.write("\u0150\u0152\5\26\f\2\u0151\u0153\5\"\22\2\u0152\u0151")
buf.write("\3\2\2\2\u0153\u0154\3\2\2\2\u0154\u0156\3\2\2\2\u0155") buf.write("\3\2\2\2\u0152\u0153\3\2\2\2\u0153\u0156\3\2\2\2\u0154")
buf.write("\u014f\3\2\2\2\u0155\u0150\3\2\2\2\u0156%\3\2\2\2\u0157") buf.write("\u0156\5\"\22\2\u0155\u014a\3\2\2\2\u0155\u014b\3\2\2")
buf.write("\u0159\5\26\f\2\u0158\u015a\5(\25\2\u0159\u0158\3\2\2") buf.write("\2\u0155\u0150\3\2\2\2\u0155\u0154\3\2\2\2\u0156%\3\2")
buf.write("\2\u0159\u015a\3\2\2\2\u015a\'\3\2\2\2\u015b\u015c\7\b") buf.write("\2\2\u0157\u0159\5\26\f\2\u0158\u015a\5(\25\2\u0159\u0158")
buf.write("\2\2\u015c\u0161\5*\26\2\u015d\u015e\7\7\2\2\u015e\u0160") buf.write("\3\2\2\2\u0159\u015a\3\2\2\2\u015a\'\3\2\2\2\u015b\u015c")
buf.write("\5*\26\2\u015f\u015d\3\2\2\2\u0160\u0163\3\2\2\2\u0161") buf.write("\7\b\2\2\u015c\u0161\5*\26\2\u015d\u015e\7\7\2\2\u015e")
buf.write("\u015f\3\2\2\2\u0161\u0162\3\2\2\2\u0162\u0164\3\2\2\2") buf.write("\u0160\5*\26\2\u015f\u015d\3\2\2\2\u0160\u0163\3\2\2\2")
buf.write("\u0163\u0161\3\2\2\2\u0164\u0165\7\t\2\2\u0165)\3\2\2") buf.write("\u0161\u015f\3\2\2\2\u0161\u0162\3\2\2\2\u0162\u0164\3")
buf.write("\2\u0166\u0169\5\b\5\2\u0167\u0169\5\26\f\2\u0168\u0166") buf.write("\2\2\2\u0163\u0161\3\2\2\2\u0164\u0165\7\t\2\2\u0165)")
buf.write("\3\2\2\2\u0168\u0167\3\2\2\2\u0169+\3\2\2\2\u016a\u0175") buf.write("\3\2\2\2\u0166\u0169\5\b\5\2\u0167\u0169\5\26\f\2\u0168")
buf.write("\5.\30\2\u016b\u016c\5\60\31\2\u016c\u016d\7\7\2\2\u016d") buf.write("\u0166\3\2\2\2\u0168\u0167\3\2\2\2\u0169+\3\2\2\2\u016a")
buf.write("\u016f\3\2\2\2\u016e\u016b\3\2\2\2\u016f\u0172\3\2\2\2") buf.write("\u0175\5.\30\2\u016b\u016c\5\60\31\2\u016c\u016d\7\7\2")
buf.write("\u0170\u016e\3\2\2\2\u0170\u0171\3\2\2\2\u0171\u0173\3") buf.write("\2\u016d\u016f\3\2\2\2\u016e\u016b\3\2\2\2\u016f\u0172")
buf.write("\2\2\2\u0172\u0170\3\2\2\2\u0173\u0175\5\62\32\2\u0174") buf.write("\3\2\2\2\u0170\u016e\3\2\2\2\u0170\u0171\3\2\2\2\u0171")
buf.write("\u016a\3\2\2\2\u0174\u0170\3\2\2\2\u0175-\3\2\2\2\u0176") buf.write("\u0173\3\2\2\2\u0172\u0170\3\2\2\2\u0173\u0175\5\62\32")
buf.write("\u017b\5\60\31\2\u0177\u0178\7\7\2\2\u0178\u017a\5\60") buf.write("\2\u0174\u016a\3\2\2\2\u0174\u0170\3\2\2\2\u0175-\3\2")
buf.write("\31\2\u0179\u0177\3\2\2\2\u017a\u017d\3\2\2\2\u017b\u0179") buf.write("\2\2\u0176\u017b\5\60\31\2\u0177\u0178\7\7\2\2\u0178\u017a")
buf.write("\3\2\2\2\u017b\u017c\3\2\2\2\u017c\u017f\3\2\2\2\u017d") buf.write("\5\60\31\2\u0179\u0177\3\2\2\2\u017a\u017d\3\2\2\2\u017b")
buf.write("\u017b\3\2\2\2\u017e\u0176\3\2\2\2\u017e\u017f\3\2\2\2") buf.write("\u0179\3\2\2\2\u017b\u017c\3\2\2\2\u017c\u017f\3\2\2\2")
buf.write("\u017f/\3\2\2\2\u0180\u0183\5\b\5\2\u0181\u0182\7\34\2") buf.write("\u017d\u017b\3\2\2\2\u017e\u0176\3\2\2\2\u017e\u017f\3")
buf.write("\2\u0182\u0184\5\66\34\2\u0183\u0181\3\2\2\2\u0183\u0184") buf.write("\2\2\2\u017f/\3\2\2\2\u0180\u0183\5\b\5\2\u0181\u0182")
buf.write("\3\2\2\2\u0184\61\3\2\2\2\u0185\u018a\5\64\33\2\u0186") buf.write("\7\34\2\2\u0182\u0184\5\66\34\2\u0183\u0181\3\2\2\2\u0183")
buf.write("\u0187\7\7\2\2\u0187\u0189\5\64\33\2\u0188\u0186\3\2\2") buf.write("\u0184\3\2\2\2\u0184\61\3\2\2\2\u0185\u018a\5\64\33\2")
buf.write("\2\u0189\u018c\3\2\2\2\u018a\u0188\3\2\2\2\u018a\u018b") buf.write("\u0186\u0187\7\7\2\2\u0187\u0189\5\64\33\2\u0188\u0186")
buf.write("\3\2\2\2\u018b\63\3\2\2\2\u018c\u018a\3\2\2\2\u018d\u018e") buf.write("\3\2\2\2\u0189\u018c\3\2\2\2\u018a\u0188\3\2\2\2\u018a")
buf.write("\7/\2\2\u018e\u018f\7\21\2\2\u018f\u0190\5\20\t\2\u0190") buf.write("\u018b\3\2\2\2\u018b\63\3\2\2\2\u018c\u018a\3\2\2\2\u018d")
buf.write("\65\3\2\2\2\u0191\u0192\7\b\2\2\u0192\u01c1\7\t\2\2\u0193") buf.write("\u018e\7/\2\2\u018e\u018f\7\21\2\2\u018f\u0190\5\20\t")
buf.write("\u0194\7\b\2\2\u0194\u0195\5\66\34\2\u0195\u0196\7\7\2") buf.write("\2\u0190\65\3\2\2\2\u0191\u0192\7\b\2\2\u0192\u01c5\7")
buf.write("\2\u0196\u0197\7\t\2\2\u0197\u01c1\3\2\2\2\u0198\u0199") buf.write("\t\2\2\u0193\u0194\7\b\2\2\u0194\u0195\5\66\34\2\u0195")
buf.write("\7\b\2\2\u0199\u019c\5\66\34\2\u019a\u019b\7\7\2\2\u019b") buf.write("\u0196\7\t\2\2\u0196\u01c5\3\2\2\2\u0197\u0198\7\b\2\2")
buf.write("\u019d\5\66\34\2\u019c\u019a\3\2\2\2\u019d\u019e\3\2\2") buf.write("\u0198\u0199\5\66\34\2\u0199\u019a\7\7\2\2\u019a\u019b")
buf.write("\2\u019e\u019c\3\2\2\2\u019e\u019f\3\2\2\2\u019f\u01a0") buf.write("\7\t\2\2\u019b\u01c5\3\2\2\2\u019c\u019d\7\b\2\2\u019d")
buf.write("\3\2\2\2\u01a0\u01a1\7\t\2\2\u01a1\u01c1\3\2\2\2\u01a2") buf.write("\u01a0\5\66\34\2\u019e\u019f\7\7\2\2\u019f\u01a1\5\66")
buf.write("\u01a3\5\4\3\2\u01a3\u01a4\58\35\2\u01a4\u01c1\3\2\2\2") buf.write("\34\2\u01a0\u019e\3\2\2\2\u01a1\u01a2\3\2\2\2\u01a2\u01a0")
buf.write("\u01a5\u01c1\5\4\3\2\u01a6\u01a7\7\35\2\2\u01a7\u01a8") buf.write("\3\2\2\2\u01a2\u01a3\3\2\2\2\u01a3\u01a4\3\2\2\2\u01a4")
buf.write("\7\n\2\2\u01a8\u01a9\5:\36\2\u01a9\u01aa\7\7\2\2\u01aa") buf.write("\u01a5\7\t\2\2\u01a5\u01c5\3\2\2\2\u01a6\u01a7\5\4\3\2")
buf.write("\u01ab\5\66\34\2\u01ab\u01ac\7\13\2\2\u01ac\u01c1\3\2") buf.write("\u01a7\u01a8\58\35\2\u01a8\u01c5\3\2\2\2\u01a9\u01c5\5")
buf.write("\2\2\u01ad\u01af\7\24\2\2\u01ae\u01b0\58\35\2\u01af\u01ae") buf.write("\4\3\2\u01aa\u01ab\7\35\2\2\u01ab\u01ac\7\n\2\2\u01ac")
buf.write("\3\2\2\2\u01af\u01b0\3\2\2\2\u01b0\u01b1\3\2\2\2\u01b1") buf.write("\u01ad\5:\36\2\u01ad\u01ae\7\7\2\2\u01ae\u01af\5\66\34")
buf.write("\u01ba\7\b\2\2\u01b2\u01b7\5\66\34\2\u01b3\u01b4\7\7\2") buf.write("\2\u01af\u01b0\7\13\2\2\u01b0\u01c5\3\2\2\2\u01b1\u01b3")
buf.write("\2\u01b4\u01b6\5\66\34\2\u01b5\u01b3\3\2\2\2\u01b6\u01b9") buf.write("\7\24\2\2\u01b2\u01b4\58\35\2\u01b3\u01b2\3\2\2\2\u01b3")
buf.write("\3\2\2\2\u01b7\u01b5\3\2\2\2\u01b7\u01b8\3\2\2\2\u01b8") buf.write("\u01b4\3\2\2\2\u01b4\u01b5\3\2\2\2\u01b5\u01be\7\b\2\2")
buf.write("\u01bb\3\2\2\2\u01b9\u01b7\3\2\2\2\u01ba\u01b2\3\2\2\2") buf.write("\u01b6\u01bb\5\66\34\2\u01b7\u01b8\7\7\2\2\u01b8\u01ba")
buf.write("\u01ba\u01bb\3\2\2\2\u01bb\u01bc\3\2\2\2\u01bc\u01bd\7") buf.write("\5\66\34\2\u01b9\u01b7\3\2\2\2\u01ba\u01bd\3\2\2\2\u01bb")
buf.write("\t\2\2\u01bd\u01be\7\25\2\2\u01be\u01c1\5\66\34\2\u01bf") buf.write("\u01b9\3\2\2\2\u01bb\u01bc\3\2\2\2\u01bc\u01bf\3\2\2\2")
buf.write("\u01c1\7\6\2\2\u01c0\u0191\3\2\2\2\u01c0\u0193\3\2\2\2") buf.write("\u01bd\u01bb\3\2\2\2\u01be\u01b6\3\2\2\2\u01be\u01bf\3")
buf.write("\u01c0\u0198\3\2\2\2\u01c0\u01a2\3\2\2\2\u01c0\u01a5\3") buf.write("\2\2\2\u01bf\u01c0\3\2\2\2\u01c0\u01c1\7\t\2\2\u01c1\u01c2")
buf.write("\2\2\2\u01c0\u01a6\3\2\2\2\u01c0\u01ad\3\2\2\2\u01c0\u01bf") buf.write("\7\25\2\2\u01c2\u01c5\5\66\34\2\u01c3\u01c5\7\6\2\2\u01c4")
buf.write("\3\2\2\2\u01c1\67\3\2\2\2\u01c2\u01c3\7\n\2\2\u01c3\u01c8") buf.write("\u0191\3\2\2\2\u01c4\u0193\3\2\2\2\u01c4\u0197\3\2\2\2")
buf.write("\5\4\3\2\u01c4\u01c5\7\7\2\2\u01c5\u01c7\5\4\3\2\u01c6") buf.write("\u01c4\u019c\3\2\2\2\u01c4\u01a6\3\2\2\2\u01c4\u01a9\3")
buf.write("\u01c4\3\2\2\2\u01c7\u01ca\3\2\2\2\u01c8\u01c6\3\2\2\2") buf.write("\2\2\2\u01c4\u01aa\3\2\2\2\u01c4\u01b1\3\2\2\2\u01c4\u01c3")
buf.write("\u01c8\u01c9\3\2\2\2\u01c9\u01cb\3\2\2\2\u01ca\u01c8\3") buf.write("\3\2\2\2\u01c5\67\3\2\2\2\u01c6\u01c7\7\n\2\2\u01c7\u01cc")
buf.write("\2\2\2\u01cb\u01cc\7\13\2\2\u01cc9\3\2\2\2\u01cd\u01ce") buf.write("\5\66\34\2\u01c8\u01c9\7\7\2\2\u01c9\u01cb\5\66\34\2\u01ca")
buf.write("\7\b\2\2\u01ce\u01db\7\t\2\2\u01cf\u01d0\7\b\2\2\u01d0") buf.write("\u01c8\3\2\2\2\u01cb\u01ce\3\2\2\2\u01cc\u01ca\3\2\2\2")
buf.write("\u01d3\5> \2\u01d1\u01d2\7\7\2\2\u01d2\u01d4\5> \2\u01d3") buf.write("\u01cc\u01cd\3\2\2\2\u01cd\u01cf\3\2\2\2\u01ce\u01cc\3")
buf.write("\u01d1\3\2\2\2\u01d4\u01d5\3\2\2\2\u01d5\u01d3\3\2\2\2") buf.write("\2\2\2\u01cf\u01d0\7\13\2\2\u01d09\3\2\2\2\u01d1\u01d2")
buf.write("\u01d5\u01d6\3\2\2\2\u01d6\u01d7\3\2\2\2\u01d7\u01d8\7") buf.write("\7\b\2\2\u01d2\u01df\7\t\2\2\u01d3\u01d4\7\b\2\2\u01d4")
buf.write("\t\2\2\u01d8\u01db\3\2\2\2\u01d9\u01db\5> \2\u01da\u01cd") buf.write("\u01d7\5> \2\u01d5\u01d6\7\7\2\2\u01d6\u01d8\5> \2\u01d7")
buf.write("\3\2\2\2\u01da\u01cf\3\2\2\2\u01da\u01d9\3\2\2\2\u01db") buf.write("\u01d5\3\2\2\2\u01d8\u01d9\3\2\2\2\u01d9\u01d7\3\2\2\2")
buf.write(";\3\2\2\2\u01dc\u01dd\7\36\2\2\u01dd\u01de\7\n\2\2\u01de") buf.write("\u01d9\u01da\3\2\2\2\u01da\u01db\3\2\2\2\u01db\u01dc\7")
buf.write("\u01df\7/\2\2\u01df\u01e0\7\13\2\2\u01e0\u01e1\7\n\2\2") buf.write("\t\2\2\u01dc\u01df\3\2\2\2\u01dd\u01df\5> \2\u01de\u01d1")
buf.write("\u01e1\u01e2\7\61\2\2\u01e2\u01e3\7\13\2\2\u01e3=\3\2") buf.write("\3\2\2\2\u01de\u01d3\3\2\2\2\u01de\u01dd\3\2\2\2\u01df")
buf.write("\2\2\u01e4\u01eb\5<\37\2\u01e5\u01e6\7\b\2\2\u01e6\u01e7") buf.write(";\3\2\2\2\u01e0\u01e1\7\36\2\2\u01e1\u01e2\7\n\2\2\u01e2")
buf.write("\5> \2\u01e7\u01e8\7\t\2\2\u01e8\u01eb\3\2\2\2\u01e9\u01eb") buf.write("\u01e3\7/\2\2\u01e3\u01e4\7\13\2\2\u01e4\u01e5\7\n\2\2")
buf.write("\7\61\2\2\u01ea\u01e4\3\2\2\2\u01ea\u01e5\3\2\2\2\u01ea") buf.write("\u01e5\u01e6\7\61\2\2\u01e6\u01e7\7\13\2\2\u01e7=\3\2")
buf.write("\u01e9\3\2\2\2\u01eb?\3\2\2\2\u01ec\u01ed\7\16\2\2\u01ed") buf.write("\2\2\u01e8\u01ef\5<\37\2\u01e9\u01ea\7\b\2\2\u01ea\u01eb")
buf.write("\u01ee\5\20\t\2\u01ee\u01ef\7\17\2\2\u01efA\3\2\2\2\u01f0") buf.write("\5> \2\u01eb\u01ec\7\t\2\2\u01ec\u01ef\3\2\2\2\u01ed\u01ef")
buf.write("\u01f4\7\60\2\2\u01f1\u01f4\7\61\2\2\u01f2\u01f4\7.\2") buf.write("\7\61\2\2\u01ee\u01e8\3\2\2\2\u01ee\u01e9\3\2\2\2\u01ee")
buf.write("\2\u01f3\u01f0\3\2\2\2\u01f3\u01f1\3\2\2\2\u01f3\u01f2") buf.write("\u01ed\3\2\2\2\u01ef?\3\2\2\2\u01f0\u01f1\7\16\2\2\u01f1")
buf.write("\3\2\2\2\u01f4C\3\2\2\2\u01f5\u01fa\5\4\3\2\u01f6\u01fa") buf.write("\u01f2\5\20\t\2\u01f2\u01f3\7\17\2\2\u01f3A\3\2\2\2\u01f4")
buf.write("\5\6\4\2\u01f7\u01fa\5\b\5\2\u01f8\u01fa\5\n\6\2\u01f9") buf.write("\u01f8\7\60\2\2\u01f5\u01f8\7\61\2\2\u01f6\u01f8\7.\2")
buf.write("\u01f5\3\2\2\2\u01f9\u01f6\3\2\2\2\u01f9\u01f7\3\2\2\2") buf.write("\2\u01f7\u01f4\3\2\2\2\u01f7\u01f5\3\2\2\2\u01f7\u01f6")
buf.write("\u01f9\u01f8\3\2\2\2\u01faE\3\2\2\28JNQZknvz\u0091\u009b") buf.write("\3\2\2\2\u01f8C\3\2\2\2\u01f9\u01fe\5\4\3\2\u01fa\u01fe")
buf.write("\u009e\u00af\u00c4\u00dd\u00df\u00e4\u00eb\u00f2\u00f9") buf.write("\5\6\4\2\u01fb\u01fe\5\b\5\2\u01fc\u01fe\5\n\6\2\u01fd")
buf.write("\u0101\u0106\u010a\u010e\u0117\u011b\u0124\u0129\u0130") buf.write("\u01f9\3\2\2\2\u01fd\u01fa\3\2\2\2\u01fd\u01fb\3\2\2\2")
buf.write("\u0134\u0138\u0140\u014a\u0153\u0155\u0159\u0161\u0168") buf.write("\u01fd\u01fc\3\2\2\2\u01feE\3\2\2\28JNQZknvz\u0091\u009b")
buf.write("\u0170\u0174\u017b\u017e\u0183\u018a\u019e\u01af\u01b7") buf.write("\u009e\u00ad\u00c2\u00db\u00dd\u00e2\u00e9\u00f0\u00f7")
buf.write("\u01ba\u01c0\u01c8\u01d5\u01da\u01ea\u01f3\u01f9") buf.write("\u00ff\u0104\u0108\u010c\u0115\u0119\u0122\u0127\u012e")
buf.write("\u0132\u013b\u0145\u014e\u0152\u0155\u0159\u0161\u0168")
buf.write("\u0170\u0174\u017b\u017e\u0183\u018a\u01a2\u01b3\u01bb")
buf.write("\u01be\u01c4\u01cc\u01d9\u01de\u01ee\u01f7\u01fd")
return buf.getvalue() return buf.getvalue()
...@@ -1180,7 +1183,7 @@ class RelayParser ( Parser ): ...@@ -1180,7 +1183,7 @@ class RelayParser ( Parser ):
self._la = 0 # Token type self._la = 0 # Token type
try: try:
self.enterOuterAlt(localctx, 1) self.enterOuterAlt(localctx, 1)
self.state = 194 self.state = 192
self._errHandler.sync(self) self._errHandler.sync(self)
la_ = self._interp.adaptivePredict(self._input,12,self._ctx) la_ = self._interp.adaptivePredict(self._input,12,self._ctx)
if la_ == 1: if la_ == 1:
...@@ -1321,22 +1324,18 @@ class RelayParser ( Parser ): ...@@ -1321,22 +1324,18 @@ class RelayParser ( Parser ):
self.state = 167 self.state = 167
self.matchType() self.matchType()
self.state = 168 self.state = 168
self.match(RelayParser.T__5)
self.state = 169
self.expr(0) self.expr(0)
self.state = 170 self.state = 169
self.match(RelayParser.T__6)
self.state = 171
self.match(RelayParser.T__11) self.match(RelayParser.T__11)
self.state = 173 self.state = 171
self._errHandler.sync(self) self._errHandler.sync(self)
_la = self._input.LA(1) _la = self._input.LA(1)
if _la==RelayParser.CNAME: if (((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << RelayParser.T__2) | (1 << RelayParser.T__3) | (1 << RelayParser.T__5) | (1 << RelayParser.CNAME))) != 0):
self.state = 172 self.state = 170
self.matchClauseList() self.matchClauseList()
self.state = 175 self.state = 173
self.match(RelayParser.T__12) self.match(RelayParser.T__12)
pass pass
...@@ -1344,17 +1343,17 @@ class RelayParser ( Parser ): ...@@ -1344,17 +1343,17 @@ class RelayParser ( Parser ):
localctx = RelayParser.LetContext(self, localctx) localctx = RelayParser.LetContext(self, localctx)
self._ctx = localctx self._ctx = localctx
_prevctx = localctx _prevctx = localctx
self.state = 177 self.state = 175
self.match(RelayParser.T__13) self.match(RelayParser.T__13)
self.state = 178 self.state = 176
self.var() self.var()
self.state = 179 self.state = 177
self.match(RelayParser.T__14) self.match(RelayParser.T__14)
self.state = 180 self.state = 178
self.expr(0) self.expr(0)
self.state = 181 self.state = 179
self.match(RelayParser.T__15) self.match(RelayParser.T__15)
self.state = 182 self.state = 180
self.expr(7) self.expr(7)
pass pass
...@@ -1362,15 +1361,15 @@ class RelayParser ( Parser ): ...@@ -1362,15 +1361,15 @@ class RelayParser ( Parser ):
localctx = RelayParser.GraphContext(self, localctx) localctx = RelayParser.GraphContext(self, localctx)
self._ctx = localctx self._ctx = localctx
_prevctx = localctx _prevctx = localctx
self.state = 184 self.state = 182
self.graphVar() self.graphVar()
self.state = 185 self.state = 183
self.match(RelayParser.T__14) self.match(RelayParser.T__14)
self.state = 186 self.state = 184
self.expr(0) self.expr(0)
self.state = 187 self.state = 185
self.match(RelayParser.T__15) self.match(RelayParser.T__15)
self.state = 188 self.state = 186
self.expr(5) self.expr(5)
pass pass
...@@ -1378,7 +1377,7 @@ class RelayParser ( Parser ): ...@@ -1378,7 +1377,7 @@ class RelayParser ( Parser ):
localctx = RelayParser.IdentExprContext(self, localctx) localctx = RelayParser.IdentExprContext(self, localctx)
self._ctx = localctx self._ctx = localctx
_prevctx = localctx _prevctx = localctx
self.state = 190 self.state = 188
self.ident() self.ident()
pass pass
...@@ -1386,7 +1385,7 @@ class RelayParser ( Parser ): ...@@ -1386,7 +1385,7 @@ class RelayParser ( Parser ):
localctx = RelayParser.ScalarExprContext(self, localctx) localctx = RelayParser.ScalarExprContext(self, localctx)
self._ctx = localctx self._ctx = localctx
_prevctx = localctx _prevctx = localctx
self.state = 191 self.state = 189
self.scalar() self.scalar()
pass pass
...@@ -1394,7 +1393,7 @@ class RelayParser ( Parser ): ...@@ -1394,7 +1393,7 @@ class RelayParser ( Parser ):
localctx = RelayParser.MetaExprContext(self, localctx) localctx = RelayParser.MetaExprContext(self, localctx)
self._ctx = localctx self._ctx = localctx
_prevctx = localctx _prevctx = localctx
self.state = 192 self.state = 190
self.meta() self.meta()
pass pass
...@@ -1402,13 +1401,13 @@ class RelayParser ( Parser ): ...@@ -1402,13 +1401,13 @@ class RelayParser ( Parser ):
localctx = RelayParser.StringExprContext(self, localctx) localctx = RelayParser.StringExprContext(self, localctx)
self._ctx = localctx self._ctx = localctx
_prevctx = localctx _prevctx = localctx
self.state = 193 self.state = 191
self.match(RelayParser.QUOTED_STRING) self.match(RelayParser.QUOTED_STRING)
pass pass
self._ctx.stop = self._input.LT(-1) self._ctx.stop = self._input.LT(-1)
self.state = 221 self.state = 219
self._errHandler.sync(self) self._errHandler.sync(self)
_alt = self._interp.adaptivePredict(self._input,14,self._ctx) _alt = self._interp.adaptivePredict(self._input,14,self._ctx)
while _alt!=2 and _alt!=ATN.INVALID_ALT_NUMBER: while _alt!=2 and _alt!=ATN.INVALID_ALT_NUMBER:
...@@ -1416,17 +1415,17 @@ class RelayParser ( Parser ): ...@@ -1416,17 +1415,17 @@ class RelayParser ( Parser ):
if self._parseListeners is not None: if self._parseListeners is not None:
self.triggerExitRuleEvent() self.triggerExitRuleEvent()
_prevctx = localctx _prevctx = localctx
self.state = 219 self.state = 217
self._errHandler.sync(self) self._errHandler.sync(self)
la_ = self._interp.adaptivePredict(self._input,13,self._ctx) la_ = self._interp.adaptivePredict(self._input,13,self._ctx)
if la_ == 1: if la_ == 1:
localctx = RelayParser.BinOpContext(self, RelayParser.ExprContext(self, _parentctx, _parentState)) localctx = RelayParser.BinOpContext(self, RelayParser.ExprContext(self, _parentctx, _parentState))
self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) self.pushNewRecursionContext(localctx, _startState, self.RULE_expr)
self.state = 196 self.state = 194
if not self.precpred(self._ctx, 19): if not self.precpred(self._ctx, 19):
from antlr4.error.Errors import FailedPredicateException from antlr4.error.Errors import FailedPredicateException
raise FailedPredicateException(self, "self.precpred(self._ctx, 19)") raise FailedPredicateException(self, "self.precpred(self._ctx, 19)")
self.state = 197 self.state = 195
localctx.op = self._input.LT(1) localctx.op = self._input.LT(1)
_la = self._input.LA(1) _la = self._input.LA(1)
if not(_la==RelayParser.MUL or _la==RelayParser.DIV): if not(_la==RelayParser.MUL or _la==RelayParser.DIV):
...@@ -1434,18 +1433,18 @@ class RelayParser ( Parser ): ...@@ -1434,18 +1433,18 @@ class RelayParser ( Parser ):
else: else:
self._errHandler.reportMatch(self) self._errHandler.reportMatch(self)
self.consume() self.consume()
self.state = 198 self.state = 196
self.expr(20) self.expr(20)
pass pass
elif la_ == 2: elif la_ == 2:
localctx = RelayParser.BinOpContext(self, RelayParser.ExprContext(self, _parentctx, _parentState)) localctx = RelayParser.BinOpContext(self, RelayParser.ExprContext(self, _parentctx, _parentState))
self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) self.pushNewRecursionContext(localctx, _startState, self.RULE_expr)
self.state = 199 self.state = 197
if not self.precpred(self._ctx, 18): if not self.precpred(self._ctx, 18):
from antlr4.error.Errors import FailedPredicateException from antlr4.error.Errors import FailedPredicateException
raise FailedPredicateException(self, "self.precpred(self._ctx, 18)") raise FailedPredicateException(self, "self.precpred(self._ctx, 18)")
self.state = 200 self.state = 198
localctx.op = self._input.LT(1) localctx.op = self._input.LT(1)
_la = self._input.LA(1) _la = self._input.LA(1)
if not(_la==RelayParser.ADD or _la==RelayParser.SUB): if not(_la==RelayParser.ADD or _la==RelayParser.SUB):
...@@ -1453,18 +1452,18 @@ class RelayParser ( Parser ): ...@@ -1453,18 +1452,18 @@ class RelayParser ( Parser ):
else: else:
self._errHandler.reportMatch(self) self._errHandler.reportMatch(self)
self.consume() self.consume()
self.state = 201 self.state = 199
self.expr(19) self.expr(19)
pass pass
elif la_ == 3: elif la_ == 3:
localctx = RelayParser.BinOpContext(self, RelayParser.ExprContext(self, _parentctx, _parentState)) localctx = RelayParser.BinOpContext(self, RelayParser.ExprContext(self, _parentctx, _parentState))
self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) self.pushNewRecursionContext(localctx, _startState, self.RULE_expr)
self.state = 202 self.state = 200
if not self.precpred(self._ctx, 17): if not self.precpred(self._ctx, 17):
from antlr4.error.Errors import FailedPredicateException from antlr4.error.Errors import FailedPredicateException
raise FailedPredicateException(self, "self.precpred(self._ctx, 17)") raise FailedPredicateException(self, "self.precpred(self._ctx, 17)")
self.state = 203 self.state = 201
localctx.op = self._input.LT(1) localctx.op = self._input.LT(1)
_la = self._input.LA(1) _la = self._input.LA(1)
if not((((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << RelayParser.LT) | (1 << RelayParser.GT) | (1 << RelayParser.LE) | (1 << RelayParser.GE))) != 0)): if not((((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << RelayParser.LT) | (1 << RelayParser.GT) | (1 << RelayParser.LE) | (1 << RelayParser.GE))) != 0)):
...@@ -1472,18 +1471,18 @@ class RelayParser ( Parser ): ...@@ -1472,18 +1471,18 @@ class RelayParser ( Parser ):
else: else:
self._errHandler.reportMatch(self) self._errHandler.reportMatch(self)
self.consume() self.consume()
self.state = 204 self.state = 202
self.expr(18) self.expr(18)
pass pass
elif la_ == 4: elif la_ == 4:
localctx = RelayParser.BinOpContext(self, RelayParser.ExprContext(self, _parentctx, _parentState)) localctx = RelayParser.BinOpContext(self, RelayParser.ExprContext(self, _parentctx, _parentState))
self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) self.pushNewRecursionContext(localctx, _startState, self.RULE_expr)
self.state = 205 self.state = 203
if not self.precpred(self._ctx, 16): if not self.precpred(self._ctx, 16):
from antlr4.error.Errors import FailedPredicateException from antlr4.error.Errors import FailedPredicateException
raise FailedPredicateException(self, "self.precpred(self._ctx, 16)") raise FailedPredicateException(self, "self.precpred(self._ctx, 16)")
self.state = 206 self.state = 204
localctx.op = self._input.LT(1) localctx.op = self._input.LT(1)
_la = self._input.LA(1) _la = self._input.LA(1)
if not(_la==RelayParser.EQ or _la==RelayParser.NE): if not(_la==RelayParser.EQ or _la==RelayParser.NE):
...@@ -1491,53 +1490,53 @@ class RelayParser ( Parser ): ...@@ -1491,53 +1490,53 @@ class RelayParser ( Parser ):
else: else:
self._errHandler.reportMatch(self) self._errHandler.reportMatch(self)
self.consume() self.consume()
self.state = 207 self.state = 205
self.expr(17) self.expr(17)
pass pass
elif la_ == 5: elif la_ == 5:
localctx = RelayParser.LetContext(self, RelayParser.ExprContext(self, _parentctx, _parentState)) localctx = RelayParser.LetContext(self, RelayParser.ExprContext(self, _parentctx, _parentState))
self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) self.pushNewRecursionContext(localctx, _startState, self.RULE_expr)
self.state = 208 self.state = 206
if not self.precpred(self._ctx, 6): if not self.precpred(self._ctx, 6):
from antlr4.error.Errors import FailedPredicateException from antlr4.error.Errors import FailedPredicateException
raise FailedPredicateException(self, "self.precpred(self._ctx, 6)") raise FailedPredicateException(self, "self.precpred(self._ctx, 6)")
self.state = 209 self.state = 207
self.match(RelayParser.T__16) self.match(RelayParser.T__16)
self.state = 210 self.state = 208
self.expr(7) self.expr(7)
pass pass
elif la_ == 6: elif la_ == 6:
localctx = RelayParser.CallContext(self, RelayParser.ExprContext(self, _parentctx, _parentState)) localctx = RelayParser.CallContext(self, RelayParser.ExprContext(self, _parentctx, _parentState))
self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) self.pushNewRecursionContext(localctx, _startState, self.RULE_expr)
self.state = 211 self.state = 209
if not self.precpred(self._ctx, 21): if not self.precpred(self._ctx, 21):
from antlr4.error.Errors import FailedPredicateException from antlr4.error.Errors import FailedPredicateException
raise FailedPredicateException(self, "self.precpred(self._ctx, 21)") raise FailedPredicateException(self, "self.precpred(self._ctx, 21)")
self.state = 212 self.state = 210
self.match(RelayParser.T__5) self.match(RelayParser.T__5)
self.state = 213 self.state = 211
self.callList() self.callList()
self.state = 214 self.state = 212
self.match(RelayParser.T__6) self.match(RelayParser.T__6)
pass pass
elif la_ == 7: elif la_ == 7:
localctx = RelayParser.ProjectionContext(self, RelayParser.ExprContext(self, _parentctx, _parentState)) localctx = RelayParser.ProjectionContext(self, RelayParser.ExprContext(self, _parentctx, _parentState))
self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) self.pushNewRecursionContext(localctx, _startState, self.RULE_expr)
self.state = 216 self.state = 214
if not self.precpred(self._ctx, 8): if not self.precpred(self._ctx, 8):
from antlr4.error.Errors import FailedPredicateException from antlr4.error.Errors import FailedPredicateException
raise FailedPredicateException(self, "self.precpred(self._ctx, 8)") raise FailedPredicateException(self, "self.precpred(self._ctx, 8)")
self.state = 217 self.state = 215
self.match(RelayParser.T__0) self.match(RelayParser.T__0)
self.state = 218 self.state = 216
self.match(RelayParser.NAT) self.match(RelayParser.NAT)
pass pass
self.state = 223 self.state = 221
self._errHandler.sync(self) self._errHandler.sync(self)
_alt = self._interp.adaptivePredict(self._input,14,self._ctx) _alt = self._interp.adaptivePredict(self._input,14,self._ctx)
...@@ -1591,33 +1590,33 @@ class RelayParser ( Parser ): ...@@ -1591,33 +1590,33 @@ class RelayParser ( Parser ):
self._la = 0 # Token type self._la = 0 # Token type
try: try:
self.enterOuterAlt(localctx, 1) self.enterOuterAlt(localctx, 1)
self.state = 224 self.state = 222
self.match(RelayParser.T__17) self.match(RelayParser.T__17)
self.state = 226 self.state = 224
self._errHandler.sync(self) self._errHandler.sync(self)
_la = self._input.LA(1) _la = self._input.LA(1)
if _la==RelayParser.T__7: if _la==RelayParser.T__7:
self.state = 225 self.state = 223
self.typeParamList() self.typeParamList()
self.state = 228 self.state = 226
self.match(RelayParser.T__5) self.match(RelayParser.T__5)
self.state = 229 self.state = 227
self.argList() self.argList()
self.state = 230 self.state = 228
self.match(RelayParser.T__6) self.match(RelayParser.T__6)
self.state = 233 self.state = 231
self._errHandler.sync(self) self._errHandler.sync(self)
_la = self._input.LA(1) _la = self._input.LA(1)
if _la==RelayParser.T__18: if _la==RelayParser.T__18:
self.state = 231 self.state = 229
self.match(RelayParser.T__18) self.match(RelayParser.T__18)
self.state = 232 self.state = 230
self.typeExpr() self.typeExpr()
self.state = 235 self.state = 233
self.body() self.body()
except RecognitionException as re: except RecognitionException as re:
localctx.exception = re localctx.exception = re
...@@ -1723,57 +1722,57 @@ class RelayParser ( Parser ): ...@@ -1723,57 +1722,57 @@ class RelayParser ( Parser ):
self.enterRule(localctx, 18, self.RULE_defn) self.enterRule(localctx, 18, self.RULE_defn)
self._la = 0 # Token type self._la = 0 # Token type
try: try:
self.state = 268 self.state = 266
self._errHandler.sync(self) self._errHandler.sync(self)
token = self._input.LA(1) token = self._input.LA(1)
if token in [RelayParser.T__19]: if token in [RelayParser.T__19]:
localctx = RelayParser.FuncDefnContext(self, localctx) localctx = RelayParser.FuncDefnContext(self, localctx)
self.enterOuterAlt(localctx, 1) self.enterOuterAlt(localctx, 1)
self.state = 237 self.state = 235
self.match(RelayParser.T__19) self.match(RelayParser.T__19)
self.state = 238 self.state = 236
self.globalVar() self.globalVar()
self.state = 240 self.state = 238
self._errHandler.sync(self) self._errHandler.sync(self)
_la = self._input.LA(1) _la = self._input.LA(1)
if _la==RelayParser.T__7: if _la==RelayParser.T__7:
self.state = 239 self.state = 237
self.typeParamList() self.typeParamList()
self.state = 242 self.state = 240
self.match(RelayParser.T__5) self.match(RelayParser.T__5)
self.state = 243 self.state = 241
self.argList() self.argList()
self.state = 244 self.state = 242
self.match(RelayParser.T__6) self.match(RelayParser.T__6)
self.state = 247 self.state = 245
self._errHandler.sync(self) self._errHandler.sync(self)
_la = self._input.LA(1) _la = self._input.LA(1)
if _la==RelayParser.T__18: if _la==RelayParser.T__18:
self.state = 245 self.state = 243
self.match(RelayParser.T__18) self.match(RelayParser.T__18)
self.state = 246 self.state = 244
self.typeExpr() self.typeExpr()
self.state = 249 self.state = 247
self.body() self.body()
pass pass
elif token in [RelayParser.T__20]: elif token in [RelayParser.T__20]:
localctx = RelayParser.ExternAdtDefnContext(self, localctx) localctx = RelayParser.ExternAdtDefnContext(self, localctx)
self.enterOuterAlt(localctx, 2) self.enterOuterAlt(localctx, 2)
self.state = 251 self.state = 249
self.match(RelayParser.T__20) self.match(RelayParser.T__20)
self.state = 252 self.state = 250
self.match(RelayParser.T__21) self.match(RelayParser.T__21)
self.state = 253 self.state = 251
self.generalIdent() self.generalIdent()
self.state = 255 self.state = 253
self._errHandler.sync(self) self._errHandler.sync(self)
_la = self._input.LA(1) _la = self._input.LA(1)
if _la==RelayParser.T__7: if _la==RelayParser.T__7:
self.state = 254 self.state = 252
self.typeParamList() self.typeParamList()
...@@ -1781,29 +1780,29 @@ class RelayParser ( Parser ): ...@@ -1781,29 +1780,29 @@ class RelayParser ( Parser ):
elif token in [RelayParser.T__21]: elif token in [RelayParser.T__21]:
localctx = RelayParser.AdtDefnContext(self, localctx) localctx = RelayParser.AdtDefnContext(self, localctx)
self.enterOuterAlt(localctx, 3) self.enterOuterAlt(localctx, 3)
self.state = 257 self.state = 255
self.match(RelayParser.T__21) self.match(RelayParser.T__21)
self.state = 258 self.state = 256
self.generalIdent() self.generalIdent()
self.state = 260 self.state = 258
self._errHandler.sync(self) self._errHandler.sync(self)
_la = self._input.LA(1) _la = self._input.LA(1)
if _la==RelayParser.T__7: if _la==RelayParser.T__7:
self.state = 259 self.state = 257
self.typeParamList() self.typeParamList()
self.state = 262 self.state = 260
self.match(RelayParser.T__11) self.match(RelayParser.T__11)
self.state = 264 self.state = 262
self._errHandler.sync(self) self._errHandler.sync(self)
_la = self._input.LA(1) _la = self._input.LA(1)
if _la==RelayParser.CNAME: if _la==RelayParser.CNAME:
self.state = 263 self.state = 261
self.adtConsDefnList() self.adtConsDefnList()
self.state = 266 self.state = 264
self.match(RelayParser.T__12) self.match(RelayParser.T__12)
pass pass
else: else:
...@@ -1845,7 +1844,7 @@ class RelayParser ( Parser ): ...@@ -1845,7 +1844,7 @@ class RelayParser ( Parser ):
self.enterRule(localctx, 20, self.RULE_constructorName) self.enterRule(localctx, 20, self.RULE_constructorName)
try: try:
self.enterOuterAlt(localctx, 1) self.enterOuterAlt(localctx, 1)
self.state = 270 self.state = 268
self.match(RelayParser.CNAME) self.match(RelayParser.CNAME)
except RecognitionException as re: except RecognitionException as re:
localctx.exception = re localctx.exception = re
...@@ -1888,26 +1887,26 @@ class RelayParser ( Parser ): ...@@ -1888,26 +1887,26 @@ class RelayParser ( Parser ):
self._la = 0 # Token type self._la = 0 # Token type
try: try:
self.enterOuterAlt(localctx, 1) self.enterOuterAlt(localctx, 1)
self.state = 272 self.state = 270
self.adtConsDefn() self.adtConsDefn()
self.state = 277 self.state = 275
self._errHandler.sync(self) self._errHandler.sync(self)
_alt = self._interp.adaptivePredict(self._input,23,self._ctx) _alt = self._interp.adaptivePredict(self._input,23,self._ctx)
while _alt!=2 and _alt!=ATN.INVALID_ALT_NUMBER: while _alt!=2 and _alt!=ATN.INVALID_ALT_NUMBER:
if _alt==1: if _alt==1:
self.state = 273 self.state = 271
self.match(RelayParser.T__4) self.match(RelayParser.T__4)
self.state = 274 self.state = 272
self.adtConsDefn() self.adtConsDefn()
self.state = 279 self.state = 277
self._errHandler.sync(self) self._errHandler.sync(self)
_alt = self._interp.adaptivePredict(self._input,23,self._ctx) _alt = self._interp.adaptivePredict(self._input,23,self._ctx)
self.state = 281 self.state = 279
self._errHandler.sync(self) self._errHandler.sync(self)
_la = self._input.LA(1) _la = self._input.LA(1)
if _la==RelayParser.T__4: if _la==RelayParser.T__4:
self.state = 280 self.state = 278
self.match(RelayParser.T__4) self.match(RelayParser.T__4)
...@@ -1956,29 +1955,29 @@ class RelayParser ( Parser ): ...@@ -1956,29 +1955,29 @@ class RelayParser ( Parser ):
self._la = 0 # Token type self._la = 0 # Token type
try: try:
self.enterOuterAlt(localctx, 1) self.enterOuterAlt(localctx, 1)
self.state = 283 self.state = 281
self.constructorName() self.constructorName()
self.state = 295 self.state = 293
self._errHandler.sync(self) self._errHandler.sync(self)
_la = self._input.LA(1) _la = self._input.LA(1)
if _la==RelayParser.T__5: if _la==RelayParser.T__5:
self.state = 284 self.state = 282
self.match(RelayParser.T__5) self.match(RelayParser.T__5)
self.state = 285 self.state = 283
self.typeExpr() self.typeExpr()
self.state = 290 self.state = 288
self._errHandler.sync(self) self._errHandler.sync(self)
_la = self._input.LA(1) _la = self._input.LA(1)
while _la==RelayParser.T__4: while _la==RelayParser.T__4:
self.state = 286 self.state = 284
self.match(RelayParser.T__4) self.match(RelayParser.T__4)
self.state = 287 self.state = 285
self.typeExpr() self.typeExpr()
self.state = 292 self.state = 290
self._errHandler.sync(self) self._errHandler.sync(self)
_la = self._input.LA(1) _la = self._input.LA(1)
self.state = 293 self.state = 291
self.match(RelayParser.T__6) self.match(RelayParser.T__6)
...@@ -2023,26 +2022,26 @@ class RelayParser ( Parser ): ...@@ -2023,26 +2022,26 @@ class RelayParser ( Parser ):
self._la = 0 # Token type self._la = 0 # Token type
try: try:
self.enterOuterAlt(localctx, 1) self.enterOuterAlt(localctx, 1)
self.state = 297 self.state = 295
self.matchClause() self.matchClause()
self.state = 302 self.state = 300
self._errHandler.sync(self) self._errHandler.sync(self)
_alt = self._interp.adaptivePredict(self._input,27,self._ctx) _alt = self._interp.adaptivePredict(self._input,27,self._ctx)
while _alt!=2 and _alt!=ATN.INVALID_ALT_NUMBER: while _alt!=2 and _alt!=ATN.INVALID_ALT_NUMBER:
if _alt==1: if _alt==1:
self.state = 298 self.state = 296
self.match(RelayParser.T__4) self.match(RelayParser.T__4)
self.state = 299 self.state = 297
self.matchClause() self.matchClause()
self.state = 304 self.state = 302
self._errHandler.sync(self) self._errHandler.sync(self)
_alt = self._interp.adaptivePredict(self._input,27,self._ctx) _alt = self._interp.adaptivePredict(self._input,27,self._ctx)
self.state = 306 self.state = 304
self._errHandler.sync(self) self._errHandler.sync(self)
_la = self._input.LA(1) _la = self._input.LA(1)
if _la==RelayParser.T__4: if _la==RelayParser.T__4:
self.state = 305 self.state = 303
self.match(RelayParser.T__4) self.match(RelayParser.T__4)
...@@ -2061,18 +2060,14 @@ class RelayParser ( Parser ): ...@@ -2061,18 +2060,14 @@ class RelayParser ( Parser ):
super().__init__(parent, invokingState) super().__init__(parent, invokingState)
self.parser = parser self.parser = parser
def constructorName(self): def pattern(self):
return self.getTypedRuleContext(RelayParser.ConstructorNameContext,0) return self.getTypedRuleContext(RelayParser.PatternContext,0)
def expr(self): def expr(self):
return self.getTypedRuleContext(RelayParser.ExprContext,0) return self.getTypedRuleContext(RelayParser.ExprContext,0)
def patternList(self):
return self.getTypedRuleContext(RelayParser.PatternListContext,0)
def getRuleIndex(self): def getRuleIndex(self):
return RelayParser.RULE_matchClause return RelayParser.RULE_matchClause
...@@ -2089,34 +2084,25 @@ class RelayParser ( Parser ): ...@@ -2089,34 +2084,25 @@ class RelayParser ( Parser ):
localctx = RelayParser.MatchClauseContext(self, self._ctx, self.state) localctx = RelayParser.MatchClauseContext(self, self._ctx, self.state)
self.enterRule(localctx, 28, self.RULE_matchClause) self.enterRule(localctx, 28, self.RULE_matchClause)
self._la = 0 # Token type
try: try:
self.enterOuterAlt(localctx, 1) self.enterOuterAlt(localctx, 1)
self.state = 308 self.state = 306
self.constructorName() self.pattern()
self.state = 310 self.state = 307
self._errHandler.sync(self)
_la = self._input.LA(1)
if _la==RelayParser.T__5:
self.state = 309
self.patternList()
self.state = 312
self.match(RelayParser.T__22) self.match(RelayParser.T__22)
self.state = 318 self.state = 313
self._errHandler.sync(self) self._errHandler.sync(self)
token = self._input.LA(1) token = self._input.LA(1)
if token in [RelayParser.T__11]: if token in [RelayParser.T__11]:
self.state = 313 self.state = 308
self.match(RelayParser.T__11) self.match(RelayParser.T__11)
self.state = 314 self.state = 309
self.expr(0) self.expr(0)
self.state = 315 self.state = 310
self.match(RelayParser.T__12) self.match(RelayParser.T__12)
pass pass
elif token in [RelayParser.T__1, RelayParser.T__2, RelayParser.T__5, RelayParser.T__7, RelayParser.T__9, RelayParser.T__13, RelayParser.T__17, RelayParser.T__23, RelayParser.T__24, RelayParser.T__27, RelayParser.QUOTED_STRING, RelayParser.SUB, RelayParser.BOOL_LIT, RelayParser.CNAME, RelayParser.FLOAT, RelayParser.NAT]: elif token in [RelayParser.T__1, RelayParser.T__2, RelayParser.T__5, RelayParser.T__7, RelayParser.T__9, RelayParser.T__13, RelayParser.T__17, RelayParser.T__23, RelayParser.T__24, RelayParser.T__27, RelayParser.QUOTED_STRING, RelayParser.SUB, RelayParser.BOOL_LIT, RelayParser.CNAME, RelayParser.FLOAT, RelayParser.NAT]:
self.state = 317 self.state = 312
self.expr(0) self.expr(0)
pass pass
else: else:
...@@ -2157,7 +2143,7 @@ class RelayParser ( Parser ): ...@@ -2157,7 +2143,7 @@ class RelayParser ( Parser ):
self._la = 0 # Token type self._la = 0 # Token type
try: try:
self.enterOuterAlt(localctx, 1) self.enterOuterAlt(localctx, 1)
self.state = 320 self.state = 315
_la = self._input.LA(1) _la = self._input.LA(1)
if not(_la==RelayParser.T__23 or _la==RelayParser.T__24): if not(_la==RelayParser.T__23 or _la==RelayParser.T__24):
self._errHandler.recoverInline(self) self._errHandler.recoverInline(self)
...@@ -2205,23 +2191,23 @@ class RelayParser ( Parser ): ...@@ -2205,23 +2191,23 @@ class RelayParser ( Parser ):
self._la = 0 # Token type self._la = 0 # Token type
try: try:
self.enterOuterAlt(localctx, 1) self.enterOuterAlt(localctx, 1)
self.state = 322 self.state = 317
self.match(RelayParser.T__5) self.match(RelayParser.T__5)
self.state = 323 self.state = 318
self.pattern() self.pattern()
self.state = 328 self.state = 323
self._errHandler.sync(self) self._errHandler.sync(self)
_la = self._input.LA(1) _la = self._input.LA(1)
while _la==RelayParser.T__4: while _la==RelayParser.T__4:
self.state = 324 self.state = 319
self.match(RelayParser.T__4) self.match(RelayParser.T__4)
self.state = 325 self.state = 320
self.pattern() self.pattern()
self.state = 330 self.state = 325
self._errHandler.sync(self) self._errHandler.sync(self)
_la = self._input.LA(1) _la = self._input.LA(1)
self.state = 331 self.state = 326
self.match(RelayParser.T__6) self.match(RelayParser.T__6)
except RecognitionException as re: except RecognitionException as re:
localctx.exception = re localctx.exception = re
...@@ -2238,26 +2224,88 @@ class RelayParser ( Parser ): ...@@ -2238,26 +2224,88 @@ class RelayParser ( Parser ):
super().__init__(parent, invokingState) super().__init__(parent, invokingState)
self.parser = parser self.parser = parser
def getRuleIndex(self):
return RelayParser.RULE_pattern
def copyFrom(self, ctx:ParserRuleContext):
super().copyFrom(ctx)
class WildcardPatternContext(PatternContext):
def __init__(self, parser, ctx:ParserRuleContext): # actually a RelayParser.PatternContext
super().__init__(parser)
self.copyFrom(ctx)
def accept(self, visitor:ParseTreeVisitor):
if hasattr( visitor, "visitWildcardPattern" ):
return visitor.visitWildcardPattern(self)
else:
return visitor.visitChildren(self)
class ConstructorPatternContext(PatternContext):
def __init__(self, parser, ctx:ParserRuleContext): # actually a RelayParser.PatternContext
super().__init__(parser)
self.copyFrom(ctx)
def constructorName(self):
return self.getTypedRuleContext(RelayParser.ConstructorNameContext,0)
def patternList(self):
return self.getTypedRuleContext(RelayParser.PatternListContext,0)
def accept(self, visitor:ParseTreeVisitor):
if hasattr( visitor, "visitConstructorPattern" ):
return visitor.visitConstructorPattern(self)
else:
return visitor.visitChildren(self)
class TuplePatternContext(PatternContext):
def __init__(self, parser, ctx:ParserRuleContext): # actually a RelayParser.PatternContext
super().__init__(parser)
self.copyFrom(ctx)
def patternList(self):
return self.getTypedRuleContext(RelayParser.PatternListContext,0)
def accept(self, visitor:ParseTreeVisitor):
if hasattr( visitor, "visitTuplePattern" ):
return visitor.visitTuplePattern(self)
else:
return visitor.visitChildren(self)
class VarPatternContext(PatternContext):
def __init__(self, parser, ctx:ParserRuleContext): # actually a RelayParser.PatternContext
super().__init__(parser)
self.copyFrom(ctx)
def localVar(self): def localVar(self):
return self.getTypedRuleContext(RelayParser.LocalVarContext,0) return self.getTypedRuleContext(RelayParser.LocalVarContext,0)
def typeExpr(self): def typeExpr(self):
return self.getTypedRuleContext(RelayParser.TypeExprContext,0) return self.getTypedRuleContext(RelayParser.TypeExprContext,0)
def getRuleIndex(self):
return RelayParser.RULE_pattern
def accept(self, visitor:ParseTreeVisitor): def accept(self, visitor:ParseTreeVisitor):
if hasattr( visitor, "visitPattern" ): if hasattr( visitor, "visitVarPattern" ):
return visitor.visitPattern(self) return visitor.visitVarPattern(self)
else: else:
return visitor.visitChildren(self) return visitor.visitChildren(self)
def pattern(self): def pattern(self):
localctx = RelayParser.PatternContext(self, self._ctx, self.state) localctx = RelayParser.PatternContext(self, self._ctx, self.state)
...@@ -2268,25 +2316,47 @@ class RelayParser ( Parser ): ...@@ -2268,25 +2316,47 @@ class RelayParser ( Parser ):
self._errHandler.sync(self) self._errHandler.sync(self)
token = self._input.LA(1) token = self._input.LA(1)
if token in [RelayParser.T__3]: if token in [RelayParser.T__3]:
localctx = RelayParser.WildcardPatternContext(self, localctx)
self.enterOuterAlt(localctx, 1) self.enterOuterAlt(localctx, 1)
self.state = 333 self.state = 328
self.match(RelayParser.T__3) self.match(RelayParser.T__3)
pass pass
elif token in [RelayParser.T__2]: elif token in [RelayParser.T__2]:
localctx = RelayParser.VarPatternContext(self, localctx)
self.enterOuterAlt(localctx, 2) self.enterOuterAlt(localctx, 2)
self.state = 334 self.state = 329
self.localVar() self.localVar()
self.state = 337 self.state = 332
self._errHandler.sync(self) self._errHandler.sync(self)
_la = self._input.LA(1) _la = self._input.LA(1)
if _la==RelayParser.T__25: if _la==RelayParser.T__25:
self.state = 335 self.state = 330
self.match(RelayParser.T__25) self.match(RelayParser.T__25)
self.state = 336 self.state = 331
self.typeExpr() self.typeExpr()
pass pass
elif token in [RelayParser.CNAME]:
localctx = RelayParser.ConstructorPatternContext(self, localctx)
self.enterOuterAlt(localctx, 3)
self.state = 334
self.constructorName()
self.state = 336
self._errHandler.sync(self)
_la = self._input.LA(1)
if _la==RelayParser.T__5:
self.state = 335
self.patternList()
pass
elif token in [RelayParser.T__5]:
localctx = RelayParser.TuplePatternContext(self, localctx)
self.enterOuterAlt(localctx, 4)
self.state = 338
self.patternList()
pass
else: else:
raise NoViableAltException(self) raise NoViableAltException(self)
...@@ -2800,6 +2870,23 @@ class RelayParser ( Parser ): ...@@ -2800,6 +2870,23 @@ class RelayParser ( Parser ):
class TypeParenContext(TypeExprContext):
def __init__(self, parser, ctx:ParserRuleContext): # actually a RelayParser.TypeExprContext
super().__init__(parser)
self.copyFrom(ctx)
def typeExpr(self):
return self.getTypedRuleContext(RelayParser.TypeExprContext,0)
def accept(self, visitor:ParseTreeVisitor):
if hasattr( visitor, "visitTypeParen" ):
return visitor.visitTypeParen(self)
else:
return visitor.visitChildren(self)
class TupleTypeContext(TypeExprContext): class TupleTypeContext(TypeExprContext):
def __init__(self, parser, ctx:ParserRuleContext): # actually a RelayParser.TypeExprContext def __init__(self, parser, ctx:ParserRuleContext): # actually a RelayParser.TypeExprContext
...@@ -2921,7 +3008,7 @@ class RelayParser ( Parser ): ...@@ -2921,7 +3008,7 @@ class RelayParser ( Parser ):
self.enterRule(localctx, 52, self.RULE_typeExpr) self.enterRule(localctx, 52, self.RULE_typeExpr)
self._la = 0 # Token type self._la = 0 # Token type
try: try:
self.state = 446 self.state = 450
self._errHandler.sync(self) self._errHandler.sync(self)
la_ = self._interp.adaptivePredict(self._input,47,self._ctx) la_ = self._interp.adaptivePredict(self._input,47,self._ctx)
if la_ == 1: if la_ == 1:
...@@ -2934,123 +3021,134 @@ class RelayParser ( Parser ): ...@@ -2934,123 +3021,134 @@ class RelayParser ( Parser ):
pass pass
elif la_ == 2: elif la_ == 2:
localctx = RelayParser.TupleTypeContext(self, localctx) localctx = RelayParser.TypeParenContext(self, localctx)
self.enterOuterAlt(localctx, 2) self.enterOuterAlt(localctx, 2)
self.state = 401 self.state = 401
self.match(RelayParser.T__5) self.match(RelayParser.T__5)
self.state = 402 self.state = 402
self.typeExpr() self.typeExpr()
self.state = 403 self.state = 403
self.match(RelayParser.T__4)
self.state = 404
self.match(RelayParser.T__6) self.match(RelayParser.T__6)
pass pass
elif la_ == 3: elif la_ == 3:
localctx = RelayParser.TupleTypeContext(self, localctx) localctx = RelayParser.TupleTypeContext(self, localctx)
self.enterOuterAlt(localctx, 3) self.enterOuterAlt(localctx, 3)
self.state = 406 self.state = 405
self.match(RelayParser.T__5) self.match(RelayParser.T__5)
self.state = 406
self.typeExpr()
self.state = 407 self.state = 407
self.match(RelayParser.T__4)
self.state = 408
self.match(RelayParser.T__6)
pass
elif la_ == 4:
localctx = RelayParser.TupleTypeContext(self, localctx)
self.enterOuterAlt(localctx, 4)
self.state = 410
self.match(RelayParser.T__5)
self.state = 411
self.typeExpr() self.typeExpr()
self.state = 410 self.state = 414
self._errHandler.sync(self) self._errHandler.sync(self)
_la = self._input.LA(1) _la = self._input.LA(1)
while True: while True:
self.state = 408 self.state = 412
self.match(RelayParser.T__4) self.match(RelayParser.T__4)
self.state = 409 self.state = 413
self.typeExpr() self.typeExpr()
self.state = 412 self.state = 416
self._errHandler.sync(self) self._errHandler.sync(self)
_la = self._input.LA(1) _la = self._input.LA(1)
if not (_la==RelayParser.T__4): if not (_la==RelayParser.T__4):
break break
self.state = 414 self.state = 418
self.match(RelayParser.T__6) self.match(RelayParser.T__6)
pass pass
elif la_ == 4: elif la_ == 5:
localctx = RelayParser.TypeCallTypeContext(self, localctx) localctx = RelayParser.TypeCallTypeContext(self, localctx)
self.enterOuterAlt(localctx, 4) self.enterOuterAlt(localctx, 5)
self.state = 416 self.state = 420
self.generalIdent() self.generalIdent()
self.state = 417 self.state = 421
self.typeParamList() self.typeParamList()
pass pass
elif la_ == 5: elif la_ == 6:
localctx = RelayParser.TypeIdentTypeContext(self, localctx) localctx = RelayParser.TypeIdentTypeContext(self, localctx)
self.enterOuterAlt(localctx, 5) self.enterOuterAlt(localctx, 6)
self.state = 419 self.state = 423
self.generalIdent() self.generalIdent()
pass pass
elif la_ == 6: elif la_ == 7:
localctx = RelayParser.TensorTypeContext(self, localctx) localctx = RelayParser.TensorTypeContext(self, localctx)
self.enterOuterAlt(localctx, 6) self.enterOuterAlt(localctx, 7)
self.state = 420 self.state = 424
self.match(RelayParser.T__26) self.match(RelayParser.T__26)
self.state = 421 self.state = 425
self.match(RelayParser.T__7) self.match(RelayParser.T__7)
self.state = 422 self.state = 426
self.shapeList() self.shapeList()
self.state = 423 self.state = 427
self.match(RelayParser.T__4) self.match(RelayParser.T__4)
self.state = 424 self.state = 428
self.typeExpr() self.typeExpr()
self.state = 425 self.state = 429
self.match(RelayParser.T__8) self.match(RelayParser.T__8)
pass pass
elif la_ == 7: elif la_ == 8:
localctx = RelayParser.FuncTypeContext(self, localctx) localctx = RelayParser.FuncTypeContext(self, localctx)
self.enterOuterAlt(localctx, 7) self.enterOuterAlt(localctx, 8)
self.state = 427 self.state = 431
self.match(RelayParser.T__17) self.match(RelayParser.T__17)
self.state = 429 self.state = 433
self._errHandler.sync(self) self._errHandler.sync(self)
_la = self._input.LA(1) _la = self._input.LA(1)
if _la==RelayParser.T__7: if _la==RelayParser.T__7:
self.state = 428 self.state = 432
self.typeParamList() self.typeParamList()
self.state = 431 self.state = 435
self.match(RelayParser.T__5) self.match(RelayParser.T__5)
self.state = 440 self.state = 444
self._errHandler.sync(self) self._errHandler.sync(self)
_la = self._input.LA(1) _la = self._input.LA(1)
if (((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << RelayParser.T__3) | (1 << RelayParser.T__5) | (1 << RelayParser.T__17) | (1 << RelayParser.T__26) | (1 << RelayParser.CNAME))) != 0): if (((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << RelayParser.T__3) | (1 << RelayParser.T__5) | (1 << RelayParser.T__17) | (1 << RelayParser.T__26) | (1 << RelayParser.CNAME))) != 0):
self.state = 432 self.state = 436
self.typeExpr() self.typeExpr()
self.state = 437 self.state = 441
self._errHandler.sync(self) self._errHandler.sync(self)
_la = self._input.LA(1) _la = self._input.LA(1)
while _la==RelayParser.T__4: while _la==RelayParser.T__4:
self.state = 433 self.state = 437
self.match(RelayParser.T__4) self.match(RelayParser.T__4)
self.state = 434 self.state = 438
self.typeExpr() self.typeExpr()
self.state = 439 self.state = 443
self._errHandler.sync(self) self._errHandler.sync(self)
_la = self._input.LA(1) _la = self._input.LA(1)
self.state = 442 self.state = 446
self.match(RelayParser.T__6) self.match(RelayParser.T__6)
self.state = 443 self.state = 447
self.match(RelayParser.T__18) self.match(RelayParser.T__18)
self.state = 444 self.state = 448
self.typeExpr() self.typeExpr()
pass pass
elif la_ == 8: elif la_ == 9:
localctx = RelayParser.IncompleteTypeContext(self, localctx) localctx = RelayParser.IncompleteTypeContext(self, localctx)
self.enterOuterAlt(localctx, 8) self.enterOuterAlt(localctx, 9)
self.state = 445 self.state = 449
self.match(RelayParser.T__3) self.match(RelayParser.T__3)
pass pass
...@@ -3070,11 +3168,11 @@ class RelayParser ( Parser ): ...@@ -3070,11 +3168,11 @@ class RelayParser ( Parser ):
super().__init__(parent, invokingState) super().__init__(parent, invokingState)
self.parser = parser self.parser = parser
def generalIdent(self, i:int=None): def typeExpr(self, i:int=None):
if i is None: if i is None:
return self.getTypedRuleContexts(RelayParser.GeneralIdentContext) return self.getTypedRuleContexts(RelayParser.TypeExprContext)
else: else:
return self.getTypedRuleContext(RelayParser.GeneralIdentContext,i) return self.getTypedRuleContext(RelayParser.TypeExprContext,i)
def getRuleIndex(self): def getRuleIndex(self):
...@@ -3096,23 +3194,23 @@ class RelayParser ( Parser ): ...@@ -3096,23 +3194,23 @@ class RelayParser ( Parser ):
self._la = 0 # Token type self._la = 0 # Token type
try: try:
self.enterOuterAlt(localctx, 1) self.enterOuterAlt(localctx, 1)
self.state = 448 self.state = 452
self.match(RelayParser.T__7) self.match(RelayParser.T__7)
self.state = 449 self.state = 453
self.generalIdent() self.typeExpr()
self.state = 454 self.state = 458
self._errHandler.sync(self) self._errHandler.sync(self)
_la = self._input.LA(1) _la = self._input.LA(1)
while _la==RelayParser.T__4: while _la==RelayParser.T__4:
self.state = 450 self.state = 454
self.match(RelayParser.T__4) self.match(RelayParser.T__4)
self.state = 451 self.state = 455
self.generalIdent() self.typeExpr()
self.state = 456 self.state = 460
self._errHandler.sync(self) self._errHandler.sync(self)
_la = self._input.LA(1) _la = self._input.LA(1)
self.state = 457 self.state = 461
self.match(RelayParser.T__8) self.match(RelayParser.T__8)
except RecognitionException as re: except RecognitionException as re:
localctx.exception = re localctx.exception = re
...@@ -3154,44 +3252,44 @@ class RelayParser ( Parser ): ...@@ -3154,44 +3252,44 @@ class RelayParser ( Parser ):
self.enterRule(localctx, 56, self.RULE_shapeList) self.enterRule(localctx, 56, self.RULE_shapeList)
self._la = 0 # Token type self._la = 0 # Token type
try: try:
self.state = 472 self.state = 476
self._errHandler.sync(self) self._errHandler.sync(self)
la_ = self._interp.adaptivePredict(self._input,50,self._ctx) la_ = self._interp.adaptivePredict(self._input,50,self._ctx)
if la_ == 1: if la_ == 1:
self.enterOuterAlt(localctx, 1) self.enterOuterAlt(localctx, 1)
self.state = 459 self.state = 463
self.match(RelayParser.T__5) self.match(RelayParser.T__5)
self.state = 460 self.state = 464
self.match(RelayParser.T__6) self.match(RelayParser.T__6)
pass pass
elif la_ == 2: elif la_ == 2:
self.enterOuterAlt(localctx, 2) self.enterOuterAlt(localctx, 2)
self.state = 461 self.state = 465
self.match(RelayParser.T__5) self.match(RelayParser.T__5)
self.state = 462 self.state = 466
self.shape() self.shape()
self.state = 465 self.state = 469
self._errHandler.sync(self) self._errHandler.sync(self)
_la = self._input.LA(1) _la = self._input.LA(1)
while True: while True:
self.state = 463 self.state = 467
self.match(RelayParser.T__4) self.match(RelayParser.T__4)
self.state = 464 self.state = 468
self.shape() self.shape()
self.state = 467 self.state = 471
self._errHandler.sync(self) self._errHandler.sync(self)
_la = self._input.LA(1) _la = self._input.LA(1)
if not (_la==RelayParser.T__4): if not (_la==RelayParser.T__4):
break break
self.state = 469 self.state = 473
self.match(RelayParser.T__6) self.match(RelayParser.T__6)
pass pass
elif la_ == 3: elif la_ == 3:
self.enterOuterAlt(localctx, 3) self.enterOuterAlt(localctx, 3)
self.state = 471 self.state = 475
self.shape() self.shape()
pass pass
...@@ -3235,19 +3333,19 @@ class RelayParser ( Parser ): ...@@ -3235,19 +3333,19 @@ class RelayParser ( Parser ):
self.enterRule(localctx, 58, self.RULE_meta) self.enterRule(localctx, 58, self.RULE_meta)
try: try:
self.enterOuterAlt(localctx, 1) self.enterOuterAlt(localctx, 1)
self.state = 474 self.state = 478
self.match(RelayParser.T__27) self.match(RelayParser.T__27)
self.state = 475 self.state = 479
self.match(RelayParser.T__7) self.match(RelayParser.T__7)
self.state = 476 self.state = 480
self.match(RelayParser.CNAME) self.match(RelayParser.CNAME)
self.state = 477 self.state = 481
self.match(RelayParser.T__8) self.match(RelayParser.T__8)
self.state = 478 self.state = 482
self.match(RelayParser.T__7) self.match(RelayParser.T__7)
self.state = 479 self.state = 483
self.match(RelayParser.NAT) self.match(RelayParser.NAT)
self.state = 480 self.state = 484
self.match(RelayParser.T__8) self.match(RelayParser.T__8)
except RecognitionException as re: except RecognitionException as re:
localctx.exception = re localctx.exception = re
...@@ -3330,29 +3428,29 @@ class RelayParser ( Parser ): ...@@ -3330,29 +3428,29 @@ class RelayParser ( Parser ):
localctx = RelayParser.ShapeContext(self, self._ctx, self.state) localctx = RelayParser.ShapeContext(self, self._ctx, self.state)
self.enterRule(localctx, 60, self.RULE_shape) self.enterRule(localctx, 60, self.RULE_shape)
try: try:
self.state = 488 self.state = 492
self._errHandler.sync(self) self._errHandler.sync(self)
token = self._input.LA(1) token = self._input.LA(1)
if token in [RelayParser.T__27]: if token in [RelayParser.T__27]:
localctx = RelayParser.MetaShapeContext(self, localctx) localctx = RelayParser.MetaShapeContext(self, localctx)
self.enterOuterAlt(localctx, 1) self.enterOuterAlt(localctx, 1)
self.state = 482 self.state = 486
self.meta() self.meta()
pass pass
elif token in [RelayParser.T__5]: elif token in [RelayParser.T__5]:
localctx = RelayParser.ParensShapeContext(self, localctx) localctx = RelayParser.ParensShapeContext(self, localctx)
self.enterOuterAlt(localctx, 2) self.enterOuterAlt(localctx, 2)
self.state = 483 self.state = 487
self.match(RelayParser.T__5) self.match(RelayParser.T__5)
self.state = 484 self.state = 488
self.shape() self.shape()
self.state = 485 self.state = 489
self.match(RelayParser.T__6) self.match(RelayParser.T__6)
pass pass
elif token in [RelayParser.NAT]: elif token in [RelayParser.NAT]:
localctx = RelayParser.IntShapeContext(self, localctx) localctx = RelayParser.IntShapeContext(self, localctx)
self.enterOuterAlt(localctx, 3) self.enterOuterAlt(localctx, 3)
self.state = 487 self.state = 491
self.match(RelayParser.NAT) self.match(RelayParser.NAT)
pass pass
else: else:
...@@ -3395,11 +3493,11 @@ class RelayParser ( Parser ): ...@@ -3395,11 +3493,11 @@ class RelayParser ( Parser ):
self.enterRule(localctx, 62, self.RULE_body) self.enterRule(localctx, 62, self.RULE_body)
try: try:
self.enterOuterAlt(localctx, 1) self.enterOuterAlt(localctx, 1)
self.state = 490 self.state = 494
self.match(RelayParser.T__11) self.match(RelayParser.T__11)
self.state = 491 self.state = 495
self.expr(0) self.expr(0)
self.state = 492 self.state = 496
self.match(RelayParser.T__12) self.match(RelayParser.T__12)
except RecognitionException as re: except RecognitionException as re:
localctx.exception = re localctx.exception = re
...@@ -3480,25 +3578,25 @@ class RelayParser ( Parser ): ...@@ -3480,25 +3578,25 @@ class RelayParser ( Parser ):
localctx = RelayParser.ScalarContext(self, self._ctx, self.state) localctx = RelayParser.ScalarContext(self, self._ctx, self.state)
self.enterRule(localctx, 64, self.RULE_scalar) self.enterRule(localctx, 64, self.RULE_scalar)
try: try:
self.state = 497 self.state = 501
self._errHandler.sync(self) self._errHandler.sync(self)
token = self._input.LA(1) token = self._input.LA(1)
if token in [RelayParser.FLOAT]: if token in [RelayParser.FLOAT]:
localctx = RelayParser.ScalarFloatContext(self, localctx) localctx = RelayParser.ScalarFloatContext(self, localctx)
self.enterOuterAlt(localctx, 1) self.enterOuterAlt(localctx, 1)
self.state = 494 self.state = 498
self.match(RelayParser.FLOAT) self.match(RelayParser.FLOAT)
pass pass
elif token in [RelayParser.NAT]: elif token in [RelayParser.NAT]:
localctx = RelayParser.ScalarIntContext(self, localctx) localctx = RelayParser.ScalarIntContext(self, localctx)
self.enterOuterAlt(localctx, 2) self.enterOuterAlt(localctx, 2)
self.state = 495 self.state = 499
self.match(RelayParser.NAT) self.match(RelayParser.NAT)
pass pass
elif token in [RelayParser.BOOL_LIT]: elif token in [RelayParser.BOOL_LIT]:
localctx = RelayParser.ScalarBoolContext(self, localctx) localctx = RelayParser.ScalarBoolContext(self, localctx)
self.enterOuterAlt(localctx, 3) self.enterOuterAlt(localctx, 3)
self.state = 496 self.state = 500
self.match(RelayParser.BOOL_LIT) self.match(RelayParser.BOOL_LIT)
pass pass
else: else:
...@@ -3552,30 +3650,30 @@ class RelayParser ( Parser ): ...@@ -3552,30 +3650,30 @@ class RelayParser ( Parser ):
localctx = RelayParser.IdentContext(self, self._ctx, self.state) localctx = RelayParser.IdentContext(self, self._ctx, self.state)
self.enterRule(localctx, 66, self.RULE_ident) self.enterRule(localctx, 66, self.RULE_ident)
try: try:
self.state = 503 self.state = 507
self._errHandler.sync(self) self._errHandler.sync(self)
la_ = self._interp.adaptivePredict(self._input,53,self._ctx) la_ = self._interp.adaptivePredict(self._input,53,self._ctx)
if la_ == 1: if la_ == 1:
self.enterOuterAlt(localctx, 1) self.enterOuterAlt(localctx, 1)
self.state = 499 self.state = 503
self.generalIdent() self.generalIdent()
pass pass
elif la_ == 2: elif la_ == 2:
self.enterOuterAlt(localctx, 2) self.enterOuterAlt(localctx, 2)
self.state = 500 self.state = 504
self.globalVar() self.globalVar()
pass pass
elif la_ == 3: elif la_ == 3:
self.enterOuterAlt(localctx, 3) self.enterOuterAlt(localctx, 3)
self.state = 501 self.state = 505
self.localVar() self.localVar()
pass pass
elif la_ == 4: elif la_ == 4:
self.enterOuterAlt(localctx, 4) self.enterOuterAlt(localctx, 4)
self.state = 502 self.state = 506
self.graphVar() self.graphVar()
pass pass
......
...@@ -184,8 +184,23 @@ class RelayVisitor(ParseTreeVisitor): ...@@ -184,8 +184,23 @@ class RelayVisitor(ParseTreeVisitor):
return self.visitChildren(ctx) return self.visitChildren(ctx)
# Visit a parse tree produced by RelayParser#pattern. # Visit a parse tree produced by RelayParser#wildcardPattern.
def visitPattern(self, ctx:RelayParser.PatternContext): def visitWildcardPattern(self, ctx:RelayParser.WildcardPatternContext):
return self.visitChildren(ctx)
# Visit a parse tree produced by RelayParser#varPattern.
def visitVarPattern(self, ctx:RelayParser.VarPatternContext):
return self.visitChildren(ctx)
# Visit a parse tree produced by RelayParser#constructorPattern.
def visitConstructorPattern(self, ctx:RelayParser.ConstructorPatternContext):
return self.visitChildren(ctx)
# Visit a parse tree produced by RelayParser#tuplePattern.
def visitTuplePattern(self, ctx:RelayParser.TuplePatternContext):
return self.visitChildren(ctx) return self.visitChildren(ctx)
...@@ -239,6 +254,11 @@ class RelayVisitor(ParseTreeVisitor): ...@@ -239,6 +254,11 @@ class RelayVisitor(ParseTreeVisitor):
return self.visitChildren(ctx) return self.visitChildren(ctx)
# Visit a parse tree produced by RelayParser#typeParen.
def visitTypeParen(self, ctx:RelayParser.TypeParenContext):
return self.visitChildren(ctx)
# Visit a parse tree produced by RelayParser#typeCallType. # Visit a parse tree produced by RelayParser#typeCallType.
def visitTypeCallType(self, ctx:RelayParser.TypeCallTypeContext): def visitTypeCallType(self, ctx:RelayParser.TypeCallTypeContext):
return self.visitChildren(ctx) return self.visitChildren(ctx)
......
...@@ -96,7 +96,7 @@ class Module(RelayNode): ...@@ -96,7 +96,7 @@ class Module(RelayNode):
assert isinstance(val, _ty.Type) assert isinstance(val, _ty.Type)
if isinstance(var, _base.string_types): if isinstance(var, _base.string_types):
var = _ty.GlobalTypeVar(var) var = _ty.GlobalTypeVar(var)
_module.Module_AddDef(self, var, val) _module.Module_AddDef(self, var, val, update)
def __getitem__(self, var): def __getitem__(self, var):
"""Lookup a global definition by name or by variable. """Lookup a global definition by name or by variable.
...@@ -149,6 +149,26 @@ class Module(RelayNode): ...@@ -149,6 +149,26 @@ class Module(RelayNode):
""" """
return _module.Module_GetGlobalVar(self, name) return _module.Module_GetGlobalVar(self, name)
def get_global_vars(self):
"""Collect all global vars defined in this module.
Returns
-------
global_vars: tvm.Array[GlobalVar]
An array of global vars.
"""
return _module.Module_GetGlobalVars(self)
def get_global_type_vars(self):
"""Collect all global type vars defined in this module.
Returns
-------
global_type_vars: tvm.Array[GlobalTypeVar]
An array of global type vars.
"""
return _module.Module_GetGlobalTypeVars(self)
def get_global_type_var(self, name): def get_global_type_var(self, name):
"""Get a global type variable in the function by name. """Get a global type variable in the function by name.
......
...@@ -16,502 +16,61 @@ ...@@ -16,502 +16,61 @@
# under the License. # under the License.
# pylint: disable=no-else-return, unidiomatic-typecheck, invalid-name # pylint: disable=no-else-return, unidiomatic-typecheck, invalid-name
"""A prelude containing useful global functions and ADT definitions.""" """A prelude containing useful global functions and ADT definitions."""
from .ty import GlobalTypeVar, TypeVar, FuncType, TupleType, scalar_type
from .expr import Var, Function, GlobalVar, Let, If, Tuple, TupleGetItem, const
from .op.tensor import add, subtract, equal
from .adt import Constructor, TypeData, Clause, Match
from .adt import PatternConstructor, PatternVar, PatternWildcard, PatternTuple
from .module import Module from .module import Module
class Prelude: class Prelude:
"""Contains standard definitions.""" """Contains standard definitions."""
def define_list_adt(self):
"""Defines a LISP-style list ADT. An empty list is
represented by nil(). A member x can be appended to the
front of a list l via the constructor cons(x, l)."""
self.l = GlobalTypeVar("list")
a = TypeVar("a")
self.nil = Constructor("nil", [], self.l)
self.cons = Constructor("cons", [a, self.l(a)], self.l)
self.mod[self.l] = TypeData(self.l, [a], [self.nil, self.cons])
def define_list_hd(self):
"""Defines a function to get the head of a list. Assume the list has at least one
element.
hd(l) : list[a] -> a
"""
self.hd = GlobalVar("hd")
a = TypeVar("a")
x = Var("x", self.l(a))
y = Var("y")
z = Var("z")
cons_case = Clause(PatternConstructor(self.cons, [PatternVar(y), PatternVar(z)]), y)
self.mod[self.hd] = Function([x], Match(x, [cons_case], False), a, [a])
def define_list_tl(self):
"""Defines a function to get the tail of a list.
tl(l) : list[a] -> list[a]
"""
self.tl = GlobalVar("tl")
a = TypeVar("a")
x = Var("x", self.l(a))
y = Var("y")
z = Var("z")
cons_case = Clause(PatternConstructor(self.cons, [PatternVar(y), PatternVar(z)]), z)
self.mod[self.tl] = Function([x], Match(x, [cons_case], False), self.l(a), [a])
def define_list_nth(self):
"""Defines a function to get the nth element of a list.
nth(l) : list[a] -> Tensor[(), int32] -> a
"""
self.nth = GlobalVar("nth")
a = TypeVar("a")
x = Var("x", self.l(a))
n = Var("n", scalar_type('int32'))
body = If(equal(n, const(0)),
self.hd(x),
self.nth(self.tl(x), subtract(n, const(1))))
self.mod[self.nth] = Function([x, n], body, a, [a])
def define_list_update(self):
"""Defines a function to update the nth element of a list and return the updated list.
update(l, i, v) : list[a] -> Tensor[(), int32] -> a -> list[a]
"""
self.update = GlobalVar("update")
a = TypeVar("a")
l = Var("l", self.l(a))
n = Var("n", scalar_type('int32'))
v = Var("v", a)
body = If(equal(n, const(0)),
self.cons(v, self.tl(l)),
self.cons(self.hd(l),
self.update(self.tl(l),
subtract(n, const(1)),
v)))
self.mod[self.update] = Function([l, n, v], body, self.l(a), [a])
def define_list_map(self):
"""Defines a function for mapping a function over a list's
elements. That is, map(f, l) returns a new list where
the ith member is f applied to the ith member of l.
map(f, l) : fn<a, b>(fn(a) -> b, list[a]) -> list[b]
"""
self.map = GlobalVar("map")
a = TypeVar("a")
b = TypeVar("b")
f = Var("f", FuncType([a], b))
x = Var("x", self.l(a))
y = Var("y")
z = Var("z")
nil_case = Clause(PatternConstructor(self.nil), self.nil())
cons_case = Clause(PatternConstructor(self.cons, [PatternVar(y), PatternVar(z)]),
self.cons(f(y), self.map(f, z)))
self.mod[self.map] = Function([f, x], Match(x, [nil_case, cons_case]), self.l(b), [a, b])
def define_list_foldl(self):
"""Defines a left-way fold over a list.
foldl(f, z, l) : fn<a, b>(fn(a, b) -> a, a, list[b]) -> a
foldl(f, z, cons(a1, cons(a2, cons(a3, cons(..., nil)))))
evaluates to f(...f(f(f(z, a1), a2), a3)...)
"""
self.foldl = GlobalVar("foldl")
a = TypeVar("a")
b = TypeVar("b")
f = Var("f", FuncType([a, b], a))
av = Var("av", a)
bv = Var("bv", self.l(b))
y = Var("y")
z = Var("z")
nil_case = Clause(PatternConstructor(self.nil), av)
cons_case = Clause(PatternConstructor(self.cons, [PatternVar(y), PatternVar(z)]),
self.foldl(f, f(av, y), z))
self.mod[self.foldl] = Function([f, av, bv],
Match(bv, [nil_case, cons_case]), a, [a, b])
def define_list_foldr(self):
"""Defines a right-way fold over a list.
foldr(f, l, z) : fn<a, b>(fn(a, b) -> b, list[a], b) -> b
foldr(f, cons(a1, cons(a2, cons(..., cons(an, nil)))), z)
evalutes to f(a1, f(a2, f(..., f(an, z)))...)
"""
self.foldr = GlobalVar("foldr")
a = TypeVar("a")
b = TypeVar("b")
f = Var("f", FuncType([a, b], b))
av = Var("av", self.l(a))
bv = Var("bv", b)
y = Var("y")
z = Var("z")
nil_case = Clause(PatternConstructor(self.nil), bv)
cons_case = Clause(PatternConstructor(self.cons, [PatternVar(y), PatternVar(z)]),
f(y, self.foldr(f, bv, z)))
self.mod[self.foldr] = Function([f, bv, av],
Match(av, [nil_case, cons_case]), b, [a, b])
def define_list_foldr1(self):
"""Defines a right-way fold over a nonempty list.
foldr1(f, l) : fn<a>(fn(a, a) -> a, list[a]) -> a
foldr1(f, cons(a1, cons(a2, cons(..., cons(an, nil)))))
evalutes to f(a1, f(a2, f(..., f(an-1, an)))...)
"""
self.foldr1 = GlobalVar("foldr1")
a = TypeVar("a")
f = Var("f", FuncType([a, a], a))
av = Var("av", self.l(a))
x = Var("x")
y = Var("y")
z = Var("z")
one_case = Clause(PatternConstructor(self.cons,
[PatternVar(x), PatternConstructor(self.nil)]), x)
cons_case = Clause(PatternConstructor(self.cons, [PatternVar(y), PatternVar(z)]),
f(y, self.foldr1(f, z)))
self.mod[self.foldr1] = Function([f, av],
Match(av, [one_case, cons_case], False), a, [a])
def define_list_concat(self):
"""Defines a function that concatenates two lists.
concat(l1, l2) : fn<a>(list[a], list[a]) -> list[a]"""
self.concat = GlobalVar("concat")
a = TypeVar("a")
l1 = Var("l1", self.l(a))
l2 = Var("l2", self.l(a))
h = Var("h")
t = Var("t")
updater = Function([h, t], self.cons(h, t))
self.mod[self.concat] = Function([l1, l2],
self.foldr(updater, l2, l1),
self.l(a), [a])
def define_list_filter(self):
"""Defines a function that filters a list.
filter(f, l) : fn<a>(fn(a) -> Tensor[(), bool], list[a]) -> list[a]
It returns the sublist of l consisting of the elements for which f returns true.
"""
self.filter = GlobalVar("filter")
a = TypeVar("a")
f = Var("f", FuncType([a], scalar_type("bool")))
l = Var("l", self.l(a))
h = Var("h")
t = Var("t")
nil_case = Clause(PatternConstructor(self.nil), self.nil())
cons_case = Clause(PatternConstructor(self.cons, [PatternVar(h), PatternVar(t)]),
If(f(h), self.cons(h, self.filter(f, t)), self.filter(f, t)))
self.mod[self.filter] = Function([f, l], Match(l, [nil_case, cons_case]), self.l(a), [a])
def define_list_zip(self):
"""Defines a function that combines two lists into a list of tuples of their elements.
zip(l, m) : fn<a, b>(list[a], list[b]) -> list[(a, b)]
The zipped list will be the length of the shorter list.
"""
self.zip = GlobalVar("zip")
a = TypeVar("a")
b = TypeVar("b")
l1 = Var("l1")
l2 = Var("l2")
h1 = Var("h1")
h2 = Var("h2")
t1 = Var("t1")
t2 = Var("t2")
cons_case = Clause(PatternTuple([PatternConstructor(self.cons,
[PatternVar(h1), PatternVar(t1)]),
PatternConstructor(self.cons,
[PatternVar(h2), PatternVar(t2)])]),
self.cons(Tuple([h1, h2]), self.zip(t1, t2)))
nil_case = Clause(PatternWildcard(), self.nil())
self.mod[self.zip] = Function([l1, l2], Match(Tuple([l1, l2]), [cons_case, nil_case]),
self.l(TupleType([a, b])), [a, b])
def define_list_rev(self):
"""Defines a function that reverses a list.
rev(l) : fn<a>(list[a]) -> list[a]
"""
self.rev = GlobalVar("rev")
a = TypeVar("a")
l = Var("l", self.l(a))
x = Var("x")
y = Var("y")
updater = Function([y, x], self.cons(x, y))
self.mod[self.rev] = Function([l],
self.foldl(updater, self.nil(), l),
self.l(a), [a])
def define_list_map_accumr(self):
"""Defines an accumulative map, which is a fold that simulataneously updates
an accumulator value and a list of results.
map_accumr(f, s, l) : fn<a, b, c>(fn(a, b) -> (a, c), a, list[b]) -> (a, list[c])
This map proceeds through l from right to left.
"""
self.map_accumr = GlobalVar("map_accumr")
a = TypeVar("a")
b = TypeVar("b")
c = TypeVar("c")
f = Var("f", FuncType([a, b], TupleType([a, c])))
acc = Var("acc", a)
l = Var("l", self.l(b))
v = Var("v", b)
p = Var("p", TupleType([a, self.l(c)]))
f_out = Var("f_out", TupleType([a, c]))
updater = Function([v, p],
Let(f_out, f(TupleGetItem(p, 0), v),
Tuple([TupleGetItem(f_out, 0),
self.cons(TupleGetItem(f_out, 1),
TupleGetItem(p, 1))])),
TupleType([a, self.l(c)]))
self.mod[self.map_accumr] = Function([f, acc, l],
self.foldr(updater, Tuple([acc, self.nil()]), l),
TupleType([a, self.l(c)]),
[a, b, c])
def define_list_map_accuml(self):
"""Defines an accumulative map, which is a fold that simulataneously updates
an accumulator value and a list of results.
map_accuml(f, s, l) : fn<a, b, c>(fn(a, b) -> (a, c), a, list[b]) -> (a, list[c])
This map proceeds through l from left to right.
"""
self.map_accuml = GlobalVar("map_accuml")
a = TypeVar("a")
b = TypeVar("b")
c = TypeVar("c")
f = Var("f", FuncType([a, b], TupleType([a, c])))
acc = Var("acc", a)
l = Var("l", self.l(b))
v = Var("v", b)
p = Var("p", TupleType([a, self.l(c)]))
f_out = Var("f_out", TupleType([a, c]))
updater = Function([p, v],
Let(f_out, f(TupleGetItem(p, 0), v),
Tuple([TupleGetItem(f_out, 0),
self.cons(TupleGetItem(f_out, 1),
TupleGetItem(p, 1))])),
TupleType([a, self.l(c)]))
self.mod[self.map_accuml] = Function([f, acc, l],
self.foldl(updater, Tuple([acc, self.nil()]), l),
TupleType([a, self.l(c)]),
[a, b, c])
def define_optional_adt(self):
"""Defines an optional ADT, which can either contain some other
type or nothing at all."""
self.optional = GlobalTypeVar("optional")
a = TypeVar("a")
self.some = Constructor("some", [a], self.optional)
self.none = Constructor("none", [], self.optional)
self.mod[self.optional] = TypeData(self.optional, [a], [self.some, self.none])
def define_list_unfoldr(self):
"""Defines a function that builds up a list starting from a seed value.
unfoldr(f, s) : fn<a, b>(fn(a) -> Optional[(a, b)], a) -> list[b]
f returns an option containing a new seed and an output value. f will
continue to be called on the new seeds until it returns None. All the
output values will be combined into a list, right to left.
"""
self.unfoldr = GlobalVar("unfoldr")
a = TypeVar("a")
b = TypeVar("b")
f = Var("f", FuncType([a], self.optional(TupleType([a, b]))))
s = Var("s", a)
p = Var("p", TupleType([a, b]))
none_case = Clause(PatternConstructor(self.none), self.nil())
some_case = Clause(PatternConstructor(self.some, [PatternVar(p)]),
self.cons(TupleGetItem(p, 1),
self.unfoldr(f, TupleGetItem(p, 0))))
self.mod[self.unfoldr] = Function([f, s], Match(f(s), [none_case, some_case]),
self.l(b), [a, b])
def define_list_unfoldl(self):
"""Defines a function that builds up a list starting from a seed value.
unfoldl(f, s) : fn<a, b>(fn(a) -> Optional[(a, b)], a) -> list[b]
f returns an option containing a new seed and an output value. f will
continue to be called on the new seeds until it returns None. All the
output values will be combined into a list, left to right.
"""
self.unfoldl = GlobalVar("unfoldl")
a = TypeVar("a")
b = TypeVar("b")
f = Var("f", FuncType([a], self.optional(TupleType([a, b]))))
s = Var("s", a)
# easiest way to implement is to do a right unfold and reverse
self.mod[self.unfoldl] = Function([f, s],
self.rev(self.unfoldr(f, s)),
self.l(b), [a, b])
def define_list_sum(self):
"""Defines a function that computes the sum of a list of integer scalars."""
self.sum = GlobalVar("sum")
a = Var("a", self.l(scalar_type('int32')))
x = Var('x')
y = Var('y')
addf = Function([x, y], add(x, y))
self.mod[self.sum] = Function([a], self.foldl(addf, const(0), a))
def define_list_length(self):
"""Defines a function that returns the length of a list"""
self.length = GlobalVar("length")
a = TypeVar("a")
x = Var("x", self.l(a))
y = Var("y")
nil_case = Clause(PatternConstructor(self.nil), const(0))
cons_case = Clause(PatternConstructor(self.cons, [PatternWildcard(), PatternVar(y)]),
add(const(1), self.length(y)))
self.mod[self.length] = Function([x],
Match(x, [nil_case, cons_case]), scalar_type('int32'), [a])
def define_tree_adt(self):
"""Defines a tree ADT. A tree can contain any type.
It has only one constructor, rose(x, l), where x is the content
of that point of the tree and l is a list of more trees of the
same type. A leaf is thus rose(x, nil()).
"""
self.tree = GlobalTypeVar("tree")
a = TypeVar("a")
self.rose = Constructor("rose", [a, self.l(self.tree(a))], self.tree)
self.mod[self.tree] = TypeData(self.tree, [a], [self.rose])
def define_tree_map(self):
"""Defines a function that maps over a tree. The function
is applied to each subtree's contents.
Signature: fn<a, b>(f : fn(a) -> b, t : tree[a]) -> tree[b]
"""
self.tmap = GlobalVar("tmap")
a = TypeVar("a")
b = TypeVar("b")
t = Var("t", self.tree(a))
f = Var("f", FuncType([a], b))
x = Var("x", self.tree(a))
y = Var("y")
z = Var("z")
rose_case = Clause(PatternConstructor(self.rose, [PatternVar(y), PatternVar(z)]),
self.rose(f(y), self.map(Function([x], self.tmap(f, x)), z)))
self.mod[self.tmap] = Function([f, t],
Match(t, [rose_case]), self.tree(b), [a, b])
def define_tree_size(self):
"""Defines a function that computes the size of a tree.
Signature: fn<a>(t : tree[a]) -> Tensor[(), int32]
"""
self.size = GlobalVar("size")
a = TypeVar("a")
t = Var("t", self.tree(a))
z = Var("z")
rose_case = Clause(PatternConstructor(self.rose, [PatternWildcard(), PatternVar(z)]),
add(const(1), self.sum(self.map(self.size, z))))
self.mod[self.size] = Function([t],
Match(t, [rose_case]), scalar_type('int32'), [a])
def define_iterate(self):
"""Defines a function that take a number n and a function f;
returns a closure that takes an argument and applies f
n times to its argument.
Signature: fn<a>(f : fn(a) -> a, n : Tensor[(), int32]) -> fn(a) -> a
"""
self.iterate = GlobalVar("iterate")
a = TypeVar("a")
f = Var("f", FuncType([a], a))
x = Var("x", scalar_type('int32'))
body = If(equal(x, const(0)),
self.id,
self.compose(f,
self.iterate(f, subtract(x, const(1)))))
self.mod[self.iterate] = Function([f, x],
body,
FuncType([a], a),
[a])
def load_prelude(self):
"""
Parses the portions of the Prelude written in Relay's text format and adds
them to the module.
"""
# TODO(@jroesch): we should remove this helper when we port over prelude
self.mod.import_from_std("prelude.rly")
self.id = self.mod.get_global_var("id")
self.compose = self.mod.get_global_var("compose")
def __init__(self, mod=None): def __init__(self, mod=None):
if mod is None: if mod is None:
mod = Module() mod = Module()
self.mod = mod self.mod = mod
self.load_prelude() self.load_prelude()
self.define_list_adt()
self.define_list_hd()
self.define_list_tl()
self.define_list_map()
self.define_list_foldl()
self.define_list_foldr()
self.define_list_foldr1()
self.define_list_concat()
self.define_list_filter()
self.define_list_zip()
self.define_list_rev()
self.define_list_map_accumr()
self.define_list_map_accuml()
self.define_optional_adt() def load_prelude(self):
self.define_list_unfoldr() """Parses the Prelude from Relay's text format into a module."""
self.define_list_unfoldl() # TODO(@jroesch): we should remove this helper when we port over prelude
self.mod.import_from_std("prelude.rly")
self.define_list_length()
self.define_list_nth()
self.define_list_update()
self.define_list_sum()
self.define_tree_adt()
self.define_tree_map()
self.define_tree_size()
self.define_iterate() self.l = self.mod.get_global_type_var("List")
list_adt = self.mod[self.l]
self.cons = list_adt.constructors[0]
self.nil = list_adt.constructors[1]
self.optional = self.mod.get_global_type_var("Option")
optional_adt = self.mod[self.optional]
self.some = optional_adt.constructors[0]
self.none = optional_adt.constructors[1]
self.tree = self.mod.get_global_type_var("Tree")
tree_adt = self.mod[self.tree]
self.rose = tree_adt.constructors[0]
GLOBAL_DEFS = [
"id",
"compose",
"flip",
"hd",
"tl",
"nth",
"update",
"map",
"foldl",
"foldr",
"foldr1",
"concat",
"filter",
"zip",
"rev",
"map_accuml",
"map_accumr",
"unfoldl",
"unfoldr",
"sum",
"length",
"tmap",
"size",
"iterate",
]
for global_def in GLOBAL_DEFS:
setattr(self, global_def, self.mod.get_global_var(global_def))
...@@ -18,12 +18,299 @@ ...@@ -18,12 +18,299 @@
*/ */
v0.0.4 v0.0.4
def @id[a](%x: a) -> a { // TODO(weberlo): should we add sugar for scalar types (e.g., `int32` => `Tensor[(), int32]`)?
%x
def @id[A](%x: A) -> A {
%x
}
def @compose[A, B, C](%f: fn(B) -> C, %g: fn(A) -> B) {
fn (%x: A) -> C {
%f(%g(%x))
}
}
def @flip[A, B, C](%f: fn(A, B) -> C) -> fn(B, A) -> C {
fn(%b: B, %a: A) -> C {
%f(%a, %b)
}
}
/*
* A LISP-style list ADT. An empty list is represented by `Nil`, and a member
* `x` can be appended to the front of a list `l` via the constructor `Cons(x, l)`.
*/
type List[A] {
Cons(A, List[A]),
Nil,
}
/*
* Get the head of a list. Assume the list has at least one element.
*/
def @hd[A](%xs: List[A]) -> A {
match? (%xs) {
Cons(%x, _) => %x,
}
}
/*
* Get the tail of a list.
*/
def @tl[A](%xs: List[A]) -> List[A] {
match? (%xs) {
Cons(_, %rest) => %rest,
}
}
/*
* Get the `n`th element of a list.
*/
def @nth[A](%xs: List[A], %n: Tensor[(), int32]) -> A {
if (%n == 0) {
@hd(%xs)
} else {
@nth(@tl(%xs), %n - 1)
}
}
/*
* Return the length of a list.
*/
def @length[A](%xs: List[A]) -> Tensor[(), int32] {
match (%xs) {
Cons(_, %rest) => 1 + @length(%rest),
Nil => 0,
}
}
/*
* Update the `n`th element of a list and return the updated list.
*/
def @update[A](%xs: List[A], %n: Tensor[(), int32], %v: A) -> List[A] {
if (%n == 0) {
Cons(%v, @tl(%xs))
} else {
Cons(@hd(%xs), @update(@tl(%xs), %n - 1, %v))
}
}
/*
* Map a function over a list's elements. That is, `map(f, xs)` returns a new
* list where the `i`th member is `f` applied to the `i`th member of `xs`.
*/
def @map[A, B](%f: fn(A) -> B, %xs: List[A]) -> List[B] {
match (%xs) {
Cons(%x, %rest) => Cons(%f(%x), @map(%f, %rest)),
Nil => Nil,
}
}
/*
* A left-way fold over a list.
*
* `foldl(f, z, cons(a1, cons(a2, cons(a3, cons(..., nil)))))`
* evaluates to `f(...f(f(f(z, a1), a2), a3)...)`.
*/
def @foldl[A, B](%f: fn(A, B) -> A, %acc: A, %xs: List[B]) -> A {
match (%xs) {
Cons(%x, %rest) => @foldl(%f, %f(%acc, %x), %rest),
Nil => %acc,
}
} }
def @compose[a, b, c](%f: fn(b) -> c, %g: fn(a) -> b) { /*
fn (%x: a) -> c { * A right-way fold over a list.
%f(%g(%x)) *
} * `foldr(f, z, cons(a1, cons(a2, cons(..., cons(an, nil)))))`
* evaluates to `f(a1, f(a2, f(..., f(an, z)))...)`.
*/
def @foldr[A, B](%f: fn(A, B) -> B, %acc: B, %xs: List[A]) -> B {
match (%xs) {
Cons(%x, %rest) => %f(%x, @foldr(%f, %acc, %rest)),
Nil => %acc,
}
}
/*
* A right-way fold over a nonempty list.
*
* `foldr1(f, cons(a1, cons(a2, cons(..., cons(an, nil)))))`
* evaluates to `f(a1, f(a2, f(..., f(an-1, an)))...)`
*/
def @foldr1[A](%f: fn(A, A) -> A, %xs: List[A]) -> A {
match? (%xs) {
Cons(%x, Nil) => %x,
Cons(%x, %rest) => %f(%x, @foldr1(%f, %rest)),
}
}
/*
* Computes the sum of a list of integer scalars.
*/
def @sum(%xs: List[Tensor[(), int32]]) {
let %add_f = fn(%x: Tensor[(), int32], %y: Tensor[(), int32]) -> Tensor[(), int32] {
%x + %y
};
@foldl(%add_f, 0, %xs)
}
/*
* Concatenates two lists.
*/
def @concat[A](%xs: List[A], %ys: List[A]) -> List[A] {
let %updater = fn(%x: A, %xss: List[A]) -> List[A] {
Cons(%x, %xss)
};
@foldr(%updater, %ys, %xs)
// TODO(weberlo): write it like below, once VM constructor compilation is fixed
// @foldr(Cons, %ys, %xs)
}
/*
* Filters a list, returning a sublist of only the values which satisfy the given predicate.
*/
def @filter[A](%f: fn(A) -> Tensor[(), bool], %xs: List[A]) -> List[A] {
match (%xs) {
Cons(%x, %rest) => {
if (%f(%x)) {
Cons(%x, @filter(%f, %rest))
} else {
@filter(%f, %rest)
}
},
Nil => Nil,
}
}
/*
* Combines two lists into a list of tuples of their elements.
*
* The zipped list will be the length of the shorter list.
*/
def @zip[A, B](%xs: List[A], %ys: List[B]) -> List[(A, B)] {
match (%xs, %ys) {
(Cons(%x, %x_rest), Cons(%y, %y_rest)) => Cons((%x, %y), @zip(%x_rest, %y_rest)),
_ => Nil,
}
}
/*
* Reverses a list.
*/
def @rev[A](%xs: List[A]) -> List[A] {
let %updater = fn(%xss: List[A], %x: A) -> List[A] {
Cons(%x, %xss)
};
@foldl(%updater, Nil, %xs)
// TODO(weberlo): write it like below, once VM constructor compilation is fixed
// @foldl(@flip(Cons), Nil, %xs)
}
/*
* An accumulative map, which is a fold that simulataneously updates an
* accumulator value and a list of results.
*
* This map proceeds through the list from right to left.
*/
def @map_accumr[A, B, C](%f: fn(A, B) -> (A, C), %init: A, %xs: List[B]) -> (A, List[C]) {
let %updater = fn(%x: B, %acc: (A, List[C])) -> (A, List[C]) {
let %f_out = %f(%acc.0, %x);
(%f_out.0, Cons(%f_out.1, %acc.1))
};
@foldr(%updater, (%init, Nil), %xs)
}
/*
* an accumulative map, which is a fold that simulataneously updates an
* accumulator value and a list of results.
*
* This map proceeds through the list from left to right.
*/
def @map_accuml[A, B, C](%f: fn(A, B) -> (A, C), %init: A, %xs: List[B]) -> (A, List[C]) {
let %updater = fn(%acc: (A, List[C]), %x: B) -> (A, List[C]) {
let %f_out = %f(%acc.0, %x);
(%f_out.0, Cons(%f_out.1, %acc.1))
};
@foldl(%updater, (%init, Nil), %xs)
}
/*
* An optional ADT, which can either contain some other type or nothing at all.
*/
type Option[A] {
Some(A),
None,
}
/*
* Builds up a list starting from a seed value.
*
* `f` returns an option containing a new seed and an output value. `f` will
* continue to be called on the new seeds until it returns `None`. All the output
* values will be combined into a list, right to left.
*/
def @unfoldr[A, B](%f: fn(A) -> Option[(A, B)], %seed: A) -> List[B] {
match (%f(%seed)) {
Some(%val) => Cons(%val.1, @unfoldr(%f, %val.0)),
None => Nil,
}
}
/*
* Builds up a list starting from a seed value.
*
* `f` returns an option containing a new seed and an output value. `f` will
* continue to be called on the new seeds until it returns `None`. All the
* output values will be combined into a list, left to right.
*/
def @unfoldl[A, B](%f: fn(A) -> Option[(A, B)], %seed: A) -> List[B] {
@rev(@unfoldr(%f, %seed))
}
/*
* A tree ADT. A tree can contain any type. It has only one
* constructor, rose(x, l), where x is the content of that point of the tree
* and l is a list of more trees of the same type. A leaf is thus rose(x,
* nil()).
*/
type Tree[A] {
Rose(A, List[Tree[A]]),
}
/*
* Maps over a tree. The function is applied to each subtree's contents.
*/
def @tmap[A, B](%f: fn(A) -> B, %t: Tree[A]) -> Tree[B] {
match(%t) {
Rose(%v, %sub_trees) => {
let %list_f = fn(%tt: Tree[A]) -> Tree[B] {
@tmap(%f, %tt)
};
Rose(%f(%v), @map(%list_f, %sub_trees))
},
}
}
/*
* Computes the size of a tree.
*/
def @size[A](%t: Tree[A]) -> Tensor[(), int32] {
match(%t) {
Rose(_, %sub_trees) => {
1 + @sum(@map(@size, %sub_trees))
},
}
}
/*
* Takes a number n and a function f; returns a closure that takes an argument
* and applies f n times to its argument.
*/
def @iterate[A](%f: fn(A) -> A, %n: Tensor[(), int32]) -> (fn(A) -> A) {
if (%n == 0) {
@id
} else {
@compose(%f, @iterate(%f, %n - 1))
}
} }
...@@ -6,9 +6,9 @@ ...@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the * to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance * "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at * with the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, * Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an * software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
......
...@@ -46,14 +46,14 @@ Module ModuleNode::make(tvm::Map<GlobalVar, Function> global_funcs, ...@@ -46,14 +46,14 @@ Module ModuleNode::make(tvm::Map<GlobalVar, Function> global_funcs,
for (const auto& kv : n->functions) { for (const auto& kv : n->functions) {
// set global var map // set global var map
CHECK(!n->global_var_map_.count(kv.first->name_hint)) CHECK(n->global_var_map_.count(kv.first->name_hint) == 0)
<< "Duplicate global function name " << kv.first->name_hint; << "Duplicate global function name " << kv.first->name_hint;
n->global_var_map_.Set(kv.first->name_hint, kv.first); n->global_var_map_.Set(kv.first->name_hint, kv.first);
} }
for (const auto& kv : n->type_definitions) { for (const auto& kv : n->type_definitions) {
// set global typevar map // set global typevar map
CHECK(!n->global_type_var_map_.count(kv.first->var->name_hint)) CHECK(n->global_type_var_map_.count(kv.first->var->name_hint) == 0)
<< "Duplicate global type definition name " << kv.first->var->name_hint; << "Duplicate global type definition name " << kv.first->var->name_hint;
n->global_type_var_map_.Set(kv.first->var->name_hint, kv.first); n->global_type_var_map_.Set(kv.first->var->name_hint, kv.first);
n->RegisterConstructors(kv.first, kv.second); n->RegisterConstructors(kv.first, kv.second);
...@@ -73,20 +73,12 @@ GlobalVar ModuleNode::GetGlobalVar(const std::string& name) const { ...@@ -73,20 +73,12 @@ GlobalVar ModuleNode::GetGlobalVar(const std::string& name) const {
return (*it).second; return (*it).second;
} }
void ModuleNode::AddUnchecked(const GlobalVar& var, tvm::Array<GlobalVar> ModuleNode::GetGlobalVars() const {
const Function& func) { std::vector<GlobalVar> global_vars;
auto mod = GetRef<Module>(this); for (const auto& pair : global_var_map_) {
this->functions.Set(var, func); global_vars.push_back(pair.second);
auto it = global_var_map_.find(var->name_hint);
if (it != global_var_map_.end()) {
CHECK_EQ((*it).second, var);
} else {
CHECK(!global_var_map_.count(var->name_hint))
<< "Duplicate global function name " << var->name_hint;
} }
return tvm::Array<GlobalVar>(global_vars);
global_var_map_.Set(var->name_hint, var);
} }
GlobalTypeVar ModuleNode::GetGlobalTypeVar(const std::string& name) const { GlobalTypeVar ModuleNode::GetGlobalTypeVar(const std::string& name) const {
...@@ -97,6 +89,14 @@ GlobalTypeVar ModuleNode::GetGlobalTypeVar(const std::string& name) const { ...@@ -97,6 +89,14 @@ GlobalTypeVar ModuleNode::GetGlobalTypeVar(const std::string& name) const {
return (*it).second; return (*it).second;
} }
tvm::Array<GlobalTypeVar> ModuleNode::GetGlobalTypeVars() const {
std::vector<GlobalTypeVar> global_type_vars;
for (const auto& pair : global_type_var_map_) {
global_type_vars.push_back(pair.second);
}
return tvm::Array<GlobalTypeVar>(global_type_vars);
}
template<typename T> template<typename T>
tvm::Array<T> concat(const tvm::Array<T>& l, const tvm::Array<T>& r) { tvm::Array<T> concat(const tvm::Array<T>& l, const tvm::Array<T>& r) {
tvm::Array<T> ret(l); tvm::Array<T> ret(l);
...@@ -151,6 +151,22 @@ void ModuleNode::Add(const GlobalVar& var, ...@@ -151,6 +151,22 @@ void ModuleNode::Add(const GlobalVar& var,
AddUnchecked(var, checked_func); AddUnchecked(var, checked_func);
} }
void ModuleNode::AddUnchecked(const GlobalVar& var,
const Function& func) {
auto mod = GetRef<Module>(this);
this->functions.Set(var, func);
auto it = global_var_map_.find(var->name_hint);
if (it != global_var_map_.end()) {
CHECK_EQ((*it).second, var);
} else {
CHECK(global_var_map_.count(var->name_hint) == 0)
<< "Duplicate global function name " << var->name_hint;
}
global_var_map_.Set(var->name_hint, var);
}
void ModuleNode::RegisterConstructors(const GlobalTypeVar& var, const TypeData& type) { void ModuleNode::RegisterConstructors(const GlobalTypeVar& var, const TypeData& type) {
// We hash the global type var name to use as a globally unique prefix for tags. // We hash the global type var name to use as a globally unique prefix for tags.
// The hash will be used as the most significant byte of the tag, with the index of // The hash will be used as the most significant byte of the tag, with the index of
...@@ -163,25 +179,33 @@ void ModuleNode::RegisterConstructors(const GlobalTypeVar& var, const TypeData& ...@@ -163,25 +179,33 @@ void ModuleNode::RegisterConstructors(const GlobalTypeVar& var, const TypeData&
} }
} }
void ModuleNode::AddDef(const GlobalTypeVar& var, const TypeData& type) { void ModuleNode::AddDef(const GlobalTypeVar& var, const TypeData& type, bool update) {
this->type_definitions.Set(var, type); AddDefUnchecked(var, type, update);
// set global type var map
CHECK(!global_type_var_map_.count(var->var->name_hint))
<< "Duplicate global type definition name " << var->var->name_hint;
global_type_var_map_.Set(var->var->name_hint, var);
RegisterConstructors(var, type);
// need to kind check at the end because the check can look up // need to kind check at the end because the check can look up
// a definition potentially // a definition potentially
CHECK(KindCheck(type, GetRef<Module>(this)) == Kind::kTypeData) CHECK(KindCheck(type, GetRef<Module>(this)) == Kind::kTypeData)
<< "Invalid or malformed typedata given to module: " << type; << "Invalid or malformed typedata given to module: " << type;
} }
void ModuleNode::AddDefUnchecked(const GlobalTypeVar& var, const TypeData& type, bool update) {
this->type_definitions.Set(var, type);
if (!update) {
// set global type var map
CHECK(global_type_var_map_.count(var->var->name_hint) == 0)
<< "Duplicate global type definition name " << var->var->name_hint;
}
global_type_var_map_.Set(var->var->name_hint, var);
RegisterConstructors(var, type);
}
void ModuleNode::Update(const GlobalVar& var, const Function& func) { void ModuleNode::Update(const GlobalVar& var, const Function& func) {
this->Add(var, func, true); this->Add(var, func, true);
} }
void ModuleNode::UpdateDef(const GlobalTypeVar& var, const TypeData& type) {
this->AddDef(var, type, true);
}
void ModuleNode::Remove(const GlobalVar& var) { void ModuleNode::Remove(const GlobalVar& var) {
auto functions_node = this->functions.CopyOnWrite(); auto functions_node = this->functions.CopyOnWrite();
functions_node->data.erase(var.node_); functions_node->data.erase(var.node_);
...@@ -226,9 +250,20 @@ Constructor ModuleNode::LookupTag(const int32_t tag) { ...@@ -226,9 +250,20 @@ Constructor ModuleNode::LookupTag(const int32_t tag) {
} }
void ModuleNode::Update(const Module& mod) { void ModuleNode::Update(const Module& mod) {
// add functions and type defs. we add them unchecked first, so all definitions
// can reference each other, independent of the order in which they were defined.
for (auto pair : mod->functions) {
this->AddUnchecked(pair.first, pair.second);
}
for (auto pair : mod->type_definitions) {
this->AddDefUnchecked(pair.first, pair.second);
}
for (auto pair : mod->functions) { for (auto pair : mod->functions) {
this->Update(pair.first, pair.second); this->Update(pair.first, pair.second);
} }
for (auto pair : mod->type_definitions) {
this->UpdateDef(pair.first, pair.second);
}
} }
Module ModuleNode::FromExpr( Module ModuleNode::FromExpr(
...@@ -257,14 +292,7 @@ void ModuleNode::Import(const std::string& path) { ...@@ -257,14 +292,7 @@ void ModuleNode::Import(const std::string& path) {
std::istreambuf_iterator<char>(src_file), std::istreambuf_iterator<char>(src_file),
std::istreambuf_iterator<char>() }; std::istreambuf_iterator<char>() };
auto mod_to_import = FromText(file_contents, path); auto mod_to_import = FromText(file_contents, path);
Update(mod_to_import);
for (auto func : mod_to_import->functions) {
this->Add(func.first, func.second, false);
}
for (auto type : mod_to_import->type_definitions) {
this->AddDef(type.first, type.second);
}
} }
} }
...@@ -315,6 +343,12 @@ TVM_REGISTER_API("relay._module.Module_AddDef") ...@@ -315,6 +343,12 @@ TVM_REGISTER_API("relay._module.Module_AddDef")
TVM_REGISTER_API("relay._module.Module_GetGlobalVar") TVM_REGISTER_API("relay._module.Module_GetGlobalVar")
.set_body_method<Module>(&ModuleNode::GetGlobalVar); .set_body_method<Module>(&ModuleNode::GetGlobalVar);
TVM_REGISTER_API("relay._module.Module_GetGlobalVars")
.set_body_method<Module>(&ModuleNode::GetGlobalVars);
TVM_REGISTER_API("relay._module.Module_GetGlobalTypeVars")
.set_body_method<Module>(&ModuleNode::GetGlobalTypeVars);
TVM_REGISTER_API("relay._module.Module_ContainGlobalVar") TVM_REGISTER_API("relay._module.Module_ContainGlobalVar")
.set_body_method<Module>(&ModuleNode::ContainGlobalVar); .set_body_method<Module>(&ModuleNode::ContainGlobalVar);
......
...@@ -570,7 +570,13 @@ class PrettyPrinter : ...@@ -570,7 +570,13 @@ class PrettyPrinter :
} else { } else {
doc << Print(op->op); doc << Print(op->op);
} }
return doc << "(" << PrintSep(args) << ")";
if (cons_node && cons_node->inputs.size() == 0) {
// don't print as a call if it's a 0-arity cons
return doc;
} else {
return doc << "(" << PrintSep(args) << ")";
}
} }
Doc VisitExpr_(const RefCreateNode* op) final { Doc VisitExpr_(const RefCreateNode* op) final {
...@@ -641,6 +647,17 @@ class PrettyPrinter : ...@@ -641,6 +647,17 @@ class PrettyPrinter :
return doc; return doc;
} }
Doc VisitPattern_(const PatternTupleNode* pt) final {
Doc doc;
doc << "(";
std::vector<Doc> pats;
for (const auto& pat : pt->patterns) {
pats.push_back(Print(pat));
}
doc << PrintSep(pats) << ")";
return doc;
}
Doc VisitPattern_(const PatternWildcardNode* pw) final { Doc VisitPattern_(const PatternWildcardNode* pw) final {
return Doc("_"); return Doc("_");
} }
......
...@@ -800,12 +800,13 @@ def test_adt_cons_expr(): ...@@ -800,12 +800,13 @@ def test_adt_cons_expr():
%s %s
def @make_singleton(%%x: int32) -> List[int32] { def @make_singleton(%%x: int32) -> List[int32] {
Cons(%%x, Nil()) Cons(%%x, Nil)
} }
""" % LIST_DEFN, """ % LIST_DEFN,
mod mod
) )
@raises_parse_error @raises_parse_error
def test_duplicate_adt_defn(): def test_duplicate_adt_defn():
parse_text( parse_text(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment