def define(cls, expr): """ GENERAL SUPPORT FOR BUILDING EXPRESSIONS FROM JSON EXPRESSIONS OVERRIDE THIS IF AN OPERATOR EXPECTS COMPLICATED PARAMETERS :param expr: Data representing a JSON Expression :return: parse tree """ try: lang = cls.lang items = items_(expr) for item in items: op, term = item full_op = operators.get(op) if full_op: class_ = lang.ops[full_op.get_id()] clauses = { k: jx_expression(v) for k, v in expr.items() if k != op } break else: if not items: return NULL raise Log.error("{{operator|quote}} is not a known operator", operator=expr) if term == None: return class_([], **clauses) elif is_container(term): terms = [jx_expression(t) for t in term] return class_(terms, **clauses) elif is_data(term): items = items_(term) if class_.has_simple_form: if len(items) == 1: k, v = items[0] return class_([Variable(k), Literal(v)], **clauses) else: return class_({k: Literal(v) for k, v in items}, **clauses) else: return class_(_jx_expression(term, lang), **clauses) else: if op in ["literal", "date", "offset"]: return class_(term, **clauses) else: return class_(_jx_expression(term, lang), **clauses) except Exception as e: Log.error("programmer error expr = {{value|quote}}", value=expr, cause=e)
def _jx_expression(expr, lang): """ WRAP A JSON EXPRESSION WITH OBJECT REPRESENTATION """ if is_expression(expr): # CONVERT TO lang new_op = lang[expr] if not new_op: # CAN NOT BE FOUND, TRY SOME PARTIAL EVAL return language[expr.get_id()].partial_eval() return expr # return new_op(expr.args) # THIS CAN BE DONE, BUT IT NEEDS MORE CODING, AND I WOULD EXPECT IT TO BE SLOW if expr is None: return TRUE elif is_text(expr): return Variable(expr) elif expr in (True, False, None) or expr == None or is_number(expr): return Literal(expr) elif expr.__class__ is Date: return Literal(expr.unix) elif is_sequence(expr): return lang[TupleOp([_jx_expression(e, lang) for e in expr])] # expr = to_data(expr) try: items = items_(expr) for op, term in items: # ONE OF THESE IS THE OPERATOR full_op = operators.get(op) if full_op: class_ = lang.ops[full_op.get_id()] if class_: return class_.define(expr) # THIS LANGUAGE DOES NOT SUPPORT THIS OPERATOR, GOTO BASE LANGUAGE AND GET THE MACRO class_ = language[op.get_id()] output = class_.define(expr).partial_eval() return _jx_expression(output, lang) else: if not items: return NULL raise Log.error("{{instruction|json}} is not known", instruction=expr) except Exception as e: Log.error("programmer error expr = {{value|quote}}", value=expr, cause=e)